﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Клиентские процедуры и функции общего назначения:
// - модуль предназначен для организации работы сервиса на стороне клиента
//  
////////////////////////////////////////////////////////////////////////////////

#Область СлужебныеПроцедурыИФункции

// Практически во всех вызовах базовых операций сервера DSS предусмотрена возможность передать уточняющие настройки через 
// структуру "ПараметрыОперации". Для каждого вида операции предусмотрен свой набор настроек, 
// но есть ряд параметров, которые являются общими для всех видов операций.
//
// 1. Через механизм "ПараметрыОперации" предусмотрена возможность подмены базовых форм, на указанные в параметрах
// Механизм подмены форм. Для его задействования необходимо передать ключ, как идентификатор формы и значение полный 
// путь к "своей" форме. При открытии формы также передаются параметры операции, как поле "ПараметрыОперации"
// Обрабатываемые ключи форм:
//	- ФормаВывестиОшибку
//	- ФормаВводПароля
//	- ФормаВводПинКода
//	- ФормаВебАутентификация
//	- ФормаНовыйЗапросНаСертификат
//	- ФормаСменаПинКода
//	- ФормаСписокСертификатов
//	- ФормаСостояниеУчетнойЗаписи
//	- ФормаСвойствоСертификата
//	- ФормаВыборТекущейУчетнойЗаписи
//	- ФормаФормаУчетнойЗаписи
//	- ФормаФормаЭкземпляраСервераDSS
//	- ФормаВыборЭкземпляровСервераDSS
//	- ФормаПроверкаСервиса
//	- ФормаВыборСервисаИзОписания
//	- ФормаПроверкаСервиса
//
// 2. Механизм трансформации данных.
// Логика возврата обработанных данных следующая: данные возвращаются с тем же типом, с каким вызывались.
// Если документ передали как "ДвоичныеДанные", то и результат будет имеет тот же тип. Предусмотрено три типов передачи 
// данных:
// 	- "ДвоичныеДанные"
// 	- "АдресХранилища"
//	- "Base64" - строка в Base64
// Но т.к. для взаимодействия клиентских вызовов с сервером используется асинхронные вызовы через фоновые задания, то 
// в случае передачи данных в виде адреса временного хранилища, требуется предварительное получение данных из хранилища
// в двоичном (строчном) виде. При возврате обработанных данных они снова помещаются во временное хранилище 
// (другой адрес), т.е. происходит неявная трансформация. Но также подобный механизм можно задействовать для изменения
// логики работы возврата результата, через поле "ТрансформироватьРезультат"
//	- ТрансформироватьРезультат - Неопределено, Структура - 
//		если передана структура, то у него должно быть поле "ТипРезультата" с вышеописанными вариантами
//
// 3. Контроль дублирования запуска одной и той же операции.
// Если в интерфейсе пользователя не предусмотрена возможность блокировки повторного нажатия кнопок, полей ввода и 
// прочих элементов, то возможна ситуация, когда будет запущено несколько асинхронных сеансов для выполнения одной
// логической операции. Одна из возможностей этого не допустить, таким операциям присваивать идентификаторы, тогда
// при создании фоновых операций будет контролироваться дублирование идентификаторов
//	- ИдентификаторОперации - Строка - произвольное уникальное обозначение, обычно уникальный идентификатор формы
//
// 4. Отображение ошибок пользователю средствами базового АПИ.
// 	- ОтобразитьОшибку - Булево, если Истина, то будет отображаться базовая форма с ошибкой
//
// 5. Отображение окна ожидания при выполнении асинхронной операции.
//	- ОжидатьВыполнения - Форма, Булево - если передано это поле, то будет отображено окно ожидания. Если оно имеет 
//										тип Форма, то она будет установлена как владелец формы ожидания.
// 
// 6. Указание режима нужного открытия формы, например режимы "Блокировка владельца" или "Независимый". По умолчанию
// формы открываются как заложено в конфигураторе. Но можно изменить подобный сценарий, передав поле 
//	- РежимОткрытияОкна - РежимОткрытияОкнаФормы - нужный тип режима открытия формы
//
// 7. Для ряда операций предусмотрено использование механизма псевдонимов, т.е. в структуре ответа будут присутствовать 
// поля с именами которые указали при вызове, иначе стандартные поля ответа предусмотренные изначально.
// В структуру ПараметровОперации необходимо добавить поле "Псевдонимы" со значением структуры, где 
//	Ключ - стандартное имя
//	Значение - альтернативное имя поля.
// Также, если в псевдонимах будет передаваться поле "ИнформацияОбОшибке", для него будет сформирован объект ИнформацияОбОшибке
//
// 8. Многие операции сопровождаются интерактивными формами, для отображения дополнительных пояснений на этих формах 
// предусмотрено поле "ПояснениеОперации" с типом строка
//
// 9. Часть ошибок возникающих при работе, таких "Неправильный пароль", "Неправильный пин-код" и прочее, обрабатывает сама.
// Если такое поведение не требуется, то нужно передать параметр:
//	- ОбработкаОшибок - Булево, если Ложь, то происходит прекращение выполнения цикла криптооперации
//
// 10. В подсистеме предусмотрена возможность выбора места хранения сессионных данных пользователей сервиса.
// Сессионные данные позволяют кешировать данные о политике настроек учетной записи на сервере, маркер безопасности и прочее.
// По-умолчанию для хранения сессионных данных используется параметр сеанса, но также есть возможность хранить их в регистре 
// "БезопасноеХранилищеДанных"
//	- ИсточникНастроек - Строка - допустимо два варианта определенны в функциях
//							СервисКриптографииDSSКлиентСервер.ИсточникНастроекПараметрыСеанса() - по-умолчанию
//							СервисКриптографииDSSКлиентСервер.ИсточникНастроекХранилище()
//
// 11. Предусмотрено регулирование режима выполнения операций в синхронном режиме или фоновом режиме.
// По-умолчанию синхронный режим не применяется для ВебКлиентов. Для изменения режима по-умолчанию, нужно передать параметр:
// - СинхронныйРежим - Булево
//

#Область АутентификацияПоЛогину

// Запускает цикл аутентификации по логину и паролю
// Данный вариант возможно использовать, если в настройках DSS включен режим: 
// "Методы первичной аутентификации: Аутентификация по паролю"
//
// Шаги цикла авторизации:
// 1. подготовка параметров цикла
// 2. при наличии ранее введенного пароля, запуск задания аутентификации (4)
// 3. ожидание ввода пароля пользователя
// 4. запуск задания аутентификации
// 5. проверка успешности ввода, если пароль неправильный, то цикл запускает заново (3)
// 6. сохранение нового токена для сеанса, возврат в случае успеха новых настроек пользователя.
//
Процедура АутентификацияПоЛогину(НастройкиПользователя, ОповещениеОЗавершении, ПараметрыОперации = Неопределено) Экспорт
	
	ВходящиеПараметры		= ПроверитьПараметрыОперации(ПараметрыОперации);
	
	ПараметрыВызова			= Новый Структура();
	ПараметрыВызова.Вставить("ВидОперации", НСтр("ru = 'Авторизация по логину'", КодЯзыка()));
	ПараметрыВызова.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыВызова.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыВызова.Вставить("ПараметрыОперации", ВходящиеПараметры);
	ПараметрыВызова.Вставить("Сохранить", Ложь);
	ПараметрыВызова.Вставить("Пароль", СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 3));
	ПараметрыВызова.Вставить("РежимСохранения", ?(СвойствоСтруктуры(ВходящиеПараметры, "СохранитьПароль", Ложь), 
									"Обязательно", "Опционально"));
	
	ПарольПользователя = СвойствоСтруктуры(ВходящиеПараметры, "ПарольПользователя");
	ПоказатьДиалогПароля = СвойствоСтруктуры(ВходящиеПараметры, "ПоказатьДиалогПароля", Ложь);
	
	Если ИспользованиеОблачнойПодписиВозможно(ПараметрыВызова) Тогда
		Если НЕ ЗначениеЗаполнено(ПарольПользователя) Тогда
			ПарольПользователя = НастройкиПользователя.Пароль;
		КонецЕсли;
		
		Если НЕ ТребуетсяВводКонфиденциальныхДанных(ПарольПользователя)
			И ПараметрыВызова.РежимСохранения <> "Обязательно"
			И НЕ ПоказатьДиалогПароля Тогда
			РезультатВвода = ОтветСервисаПоУмолчанию();
			РезультатВвода.Вставить("Результат", ПарольПользователя);
			РезультатВвода.Вставить("Сохранить", Ложь);
			АутентификацияПоЛогинуПолучениеПароля(РезультатВвода, ПараметрыВызова);
		Иначе
			АутентификацияПоЛогинуЗапросПароля(Неопределено, ПараметрыВызова);
		КонецЕсли;
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры АутентификацияПоЛогину.
Процедура АутентификацияПоЛогинуЗапросПароля(РезультатВыбора, ВходящийКонтекст) Экспорт
	
	ОбъектОповещения		= Новый ОписаниеОповещения("АутентификацияПоЛогинуПолучениеПароля", ЭтотОбъект);
	ОповещениеСледующее 	= ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	
	ОткрытьФормуВводПароля(
		ВходящийКонтекст.НастройкиПользователя,
		ОповещениеСледующее,
		"Пароль", 
		ВходящийКонтекст.РежимСохранения,
		ВходящийКонтекст.ПараметрыОперации);
		
КонецПроцедуры

// Продолжение процедуры АутентификацияПоЛогину.
Процедура АутентификацияПоЛогинуПолучениеПароля(РезультатВыбора, ВходящийКонтекст) Экспорт
	
	Если РезультатВыбора.Выполнено Тогда
		ВходящийКонтекст.Вставить("Сохранить", РезультатВыбора.Сохранить);
		ВходящийКонтекст.Вставить("Пароль", РезультатВыбора.Результат);
		ВходящийКонтекст.НастройкиПользователя.Пароль = РезультатВыбора.Результат;
		
		ОбъектОповещения	= Новый ОписаниеОповещения("АутентификацияПоЛогинуПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
		
		ДлительнаяОперация = СервисКриптографииDSSСлужебныйВызовСервера.АутентификацияПоЛогину(ВходящийКонтекст.НастройкиПользователя, 
								ВходящийКонтекст.ПараметрыОперации);
								
		ОжидатьЗавершенияВыполненияВФоне(
			ОповещениеСледующее, 
			ДлительнаяОперация,
			ВходящийКонтекст.ПараметрыОперации);	
	Иначе
		АутентификацияПоЛогинуРезультат(РезультатВыбора, ВходящийКонтекст);
	КонецЕсли;	

КонецПроцедуры

// Продолжение процедуры АутентификацияПоЛогину.
Процедура АутентификацияПоЛогинуПослеВыполнения(РезультатВызова, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(РезультатВызова, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		НастройкиПользователя = РезультатВыполнения.НастройкиПользователя;
		Если ВходящийКонтекст.Сохранить Тогда
			СохранитьЗакрытыеДанные(НастройкиПользователя.УникальныйИдентификатор, ВходящийКонтекст.Пароль, "Пароль");
		КонецЕсли;	
	Иначе
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		НастройкиПользователя.Пароль = СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 3);
	КонецЕсли;
	ИзменитьСчетчикПопыток(НастройкиПользователя, РезультатВыполнения.Выполнено);
	РезультатВыполнения.Вставить("НастройкиПользователя", НастройкиПользователя);
	
	Если СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) 
		И НЕ НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ОбъектОповещения	= Новый ОписаниеОповещения("АутентификацияПоЛогинуЗапросПароля", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ОтобразитьОшибкуПользователю(ОповещениеСледующее, РезультатВыполнения.Ошибка, , ВходящийКонтекст.ПараметрыОперации);
	Иначе
		АутентификацияПоЛогинуРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры АутентификацияПоЛогину.
Процедура АутентификацияПоЛогинуРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область АутентификацияПоСертификату

// Запускает цикл авторизации по сертификату авторизации.
// На данный момент работает только сертификат с закрытым ключом выпущенный с использованием алгоритма RSA и
// экспортированный в файл PFX, доступ к которому запрашивается пароль
// Данный вариант возможно использовать, если в настройках DSS включен режим: 
// "Методы первичной аутентификации: Аутентификация по сертификату"
//
// Шаги цикла:
// 1. подготовка параметров цикла авторизации
// 2. при наличии ранее введенного пароля, запуск задания аутентификации (4)
// 3. ожидание ввода пароля пользователя
// 4. запуск задания аутентификации
// 5. проверка успешности ввода, если пароль неправильный, то цикл запускает заново (3)
// 6. сохранение нового токена для сеанса, возврат в случае успеха новых настроек пользователя.
//
Процедура АутентификацияПоСертификату(НастройкиПользователя, ОповещениеОЗавершении, ПараметрыОперации = Неопределено) Экспорт
	
	ВходящиеПараметры		= ПроверитьПараметрыОперации(ПараметрыОперации);
	
	ПараметрыВызова			= Новый Структура();
	ПараметрыВызова.Вставить("ВидОперации", НСтр("ru = 'Авторизация по сертификату'", КодЯзыка()));
	ПараметрыВызова.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыВызова.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыВызова.Вставить("ПараметрыОперации", ВходящиеПараметры);
	ПараметрыВызова.Вставить("Сохранить", Ложь);
	ПараметрыВызова.Вставить("Пароль", СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 3));
	ПараметрыВызова.Вставить("РежимСохранения", ?(СвойствоСтруктуры(ВходящиеПараметры, "СохранитьПароль", Ложь), 
									"Обязательно", "Опционально"));
	
	ПарольПользователя = СвойствоСтруктуры(ВходящиеПараметры, "ПарольПользователя");
	ПоказатьДиалогПароля = СвойствоСтруктуры(ВходящиеПараметры, "ПоказатьДиалогПароля", Ложь);
	
	Если ИспользованиеОблачнойПодписиВозможно(ПараметрыВызова) Тогда
		Если НЕ ЗначениеЗаполнено(ПарольПользователя) Тогда
			ПарольПользователя = НастройкиПользователя.ПарольСертификата;
		КонецЕсли;
		
		Если НЕ ТребуетсяВводКонфиденциальныхДанных(ПарольПользователя)
			И ПараметрыВызова.РежимСохранения <> "Обязательно"
			И НЕ ПоказатьДиалогПароля Тогда
			РезультатВвода = ОтветСервисаПоУмолчанию();
			РезультатВвода.Вставить("Сохранить", Ложь);
			РезультатВвода.Вставить("Результат", ПарольПользователя);
			АутентификацияПоСертификатуПолучениеПинКода(РезультатВвода, ПараметрыВызова);
		Иначе
			АутентификацияПоСертификатуЗапросПинКода(Неопределено, ПараметрыВызова);
		КонецЕсли;
	КонецЕсли;	

КонецПроцедуры

// Продолжение процедуры АутентификацияПоСертификату.
Процедура АутентификацияПоСертификатуЗапросПинКода(РезультатВыбора, ВходящийКонтекст) Экспорт
	
	ОбъектОповещения	= Новый ОписаниеОповещения("АутентификацияПоСертификатуПолучениеПинКода", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	
	ОткрытьФормуВводПароля(
		ВходящийКонтекст.НастройкиПользователя,
		ОповещениеСледующее,
		"ПинКод", 
		ВходящийКонтекст.РежимСохранения,
		ВходящийКонтекст.ПараметрыОперации);
	
КонецПроцедуры

// Продолжение процедуры АутентификацияПоСертификату.
Процедура АутентификацияПоСертификатуПолучениеПинКода(РезультатВыбора, ВходящийКонтекст) Экспорт
	
	Если РезультатВыбора.Выполнено Тогда
		СертификатАвторизации = СвойствоСтруктуры(РезультатВыбора, "СертификатАвторизации");
		
		ПараметрыОперации = ВходящийКонтекст.ПараметрыОперации;
		Если СертификатАвторизации <> Неопределено Тогда
			ПараметрыОперации.Вставить("СертификатАвторизации", СертификатАвторизации);
		КонецЕсли;
		
		ВходящийКонтекст.Вставить("Сохранить", РезультатВыбора.Сохранить);
		ВходящийКонтекст.Вставить("Пароль", РезультатВыбора.Результат);
		ВходящийКонтекст.НастройкиПользователя.ПарольСертификата = РезультатВыбора.Результат;
		
		ОбъектОповещения	= Новый ОписаниеОповещения("АутентификацияПоСертификатуПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
		
		ОжидатьЗавершенияВыполненияВФоне(
			ОповещениеСледующее, 
			СервисКриптографииDSSСлужебныйВызовСервера.АутентификацияПоСертификату(ВходящийКонтекст.НастройкиПользователя, ПараметрыОперации),
			ВходящийКонтекст.ПараметрыОперации);
	Иначе		
		АутентификацияПоСертификатуРезультат(РезультатВыбора, ВходящийКонтекст);
	КонецЕсли;	

КонецПроцедуры

// Продолжение процедуры АутентификацияПоСертификату.
Процедура АутентификацияПоСертификатуПослеВыполнения(РезультатВызова, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(РезультатВызова, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		НастройкиПользователя 	= РезультатВыполнения.НастройкиПользователя;
		Если ВходящийКонтекст.Сохранить Тогда
			СохранитьЗакрытыеДанные(НастройкиПользователя.УникальныйИдентификатор, ВходящийКонтекст.Пароль, "ПарольСертификата");
		КонецЕсли;	
	Иначе
		НастройкиПользователя 	= ВходящийКонтекст.НастройкиПользователя;
		НастройкиПользователя.ПарольСертификата = СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 3);
	КонецЕсли;
	ИзменитьСчетчикПопыток(НастройкиПользователя, РезультатВыполнения.Выполнено);
		
	Если СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) 
		И НЕ НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ОбъектОповещения	= Новый ОписаниеОповещения("АутентификацияПоСертификатуЗапросПинКода", ЭтотОбъект);
		ОповещениеСледующее	= ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ОтобразитьОшибкуПользователю(ОповещениеСледующее, РезультатВыполнения.Ошибка, , ВходящийКонтекст.ПараметрыОперации);
	Иначе
		РезультатВыполнения.МаркерОбновлен = Истина;
		РезультатВыполнения.Вставить("НастройкиПользователя", НастройкиПользователя);
		АутентификацияПоСертификатуРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры АутентификацияПоСертификату.
Процедура АутентификацияПоСертификатуРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область АутентификацияДвухФакторная

// Запускает цикл двухфакторной аутентификации (с подтверждением)
// Данный вариант возможно использовать, если в настройках DSS включены режимы: 
// "Методы первичной аутентификации: Аутентификация по паролю"
// "Подтверждение операций: Выпуск маркера",
// иначе произойдет обычная авторизация по логину и паролю или выдаст ошибку
//
// Шаги цикла:
// 1. подготовка параметров цикла авторизации
// 2. при наличии ранее введенного пароля, запуск задания аутентификации (4)
// 3. ожидание ввода пароля пользователя
// 4. запуск вложенного процесса подтверждения
// 5. проверка успешности ввода, если пароль неправильный, то цикл запускает заново (3)
// 6. сохранение нового токена для сеанса
// 7. обновления политик учетной записи
// 8. возврат в случае успеха новых настроек пользователя.
// 
Процедура АутентификацияДвухФакторная(НастройкиПользователя, ОповещениеОЗавершении, ПараметрыОперации = Неопределено) Экспорт
	
	ВходящиеПараметры		= ПроверитьПараметрыОперации(ПараметрыОперации);
	
	ПараметрыВызова			= Новый Структура();
	ПараметрыВызова.Вставить("ВидОперации", НСтр("ru = 'Авторизация двух-факторная'", КодЯзыка()));
	ПараметрыВызова.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыВызова.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыВызова.Вставить("ПараметрыОперации", ВходящиеПараметры);
	ПараметрыВызова.Вставить("Сохранить", Ложь);
	ПараметрыВызова.Вставить("Пароль", СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 3));
	ПараметрыВызова.Вставить("РежимСохранения", ?(СвойствоСтруктуры(ВходящиеПараметры, "СохранитьПароль", Ложь), 
									"Обязательно", "Опционально"));
	
	ПарольПользователя = СвойствоСтруктуры(ВходящиеПараметры, "ПарольПользователя");
	ПоказатьДиалогПароля = СвойствоСтруктуры(ВходящиеПараметры, "ПоказатьДиалогПароля", Ложь);
	
	Если ИспользованиеОблачнойПодписиВозможно(ПараметрыВызова) Тогда
		Если НЕ ЗначениеЗаполнено(ПарольПользователя) Тогда
			ПарольПользователя = НастройкиПользователя.Пароль;
		КонецЕсли;
		
		Если НЕ ТребуетсяВводКонфиденциальныхДанных(ПарольПользователя)
			И ПараметрыВызова.РежимСохранения <> "Обязательно"
			И НЕ ПоказатьДиалогПароля Тогда
			РезультатВвода = ОтветСервисаПоУмолчанию();
			РезультатВвода.Вставить("Результат", ПарольПользователя);
			РезультатВвода.Вставить("Сохранить", Ложь);
			АутентификацияДвухФакторнаяПолучениеПароля(РезультатВвода, ПараметрыВызова);
		Иначе
			АутентификацияДвухФакторнаяЗапросПароля(Неопределено, ПараметрыВызова);
		КонецЕсли;
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры АутентификацияДвухФакторная.
Процедура АутентификацияДвухФакторнаяЗапросПароля(РезультатВызова, ВходящийКонтекст) Экспорт
	
	ОбъектОповещения		= Новый ОписаниеОповещения("АутентификацияДвухФакторнаяПолучениеПароля", ЭтотОбъект);
	ОповещениеСледующее 	= ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);

	ПояснениеОперации		= СвойствоСтруктуры(ВходящийКонтекст.ПараметрыОперации, "ПояснениеОперации", "");
	Если Не ЗначениеЗаполнено(ПояснениеОперации) Тогда
		ПояснениеОперации	= НСтр("ru = 'Введите пароль для авторизации.'", КодЯзыка());
	КонецЕсли;
	ВходящийКонтекст.ПараметрыОперации.Вставить("ПояснениеОперации", ПояснениеОперации);
	
	ОткрытьФормуВводПароля(
		ВходящийКонтекст.НастройкиПользователя,
		ОповещениеСледующее,
		"Пароль", 
		ВходящийКонтекст.РежимСохранения,
		ВходящийКонтекст.ПараметрыОперации);

КонецПроцедуры

// Продолжение процедуры АутентификацияДвухФакторная.
Процедура АутентификацияДвухФакторнаяПолучениеПароля(РезультатВызова, ВходящийКонтекст) Экспорт
	
	ОбъектОповещения	= Новый ОписаниеОповещения("АутентификацияДвухФакторнаяПослеВыполнения", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	
	Если РезультатВызова.Выполнено Тогда
		ВходящийКонтекст.Вставить("Сохранить", РезультатВызова.Сохранить);
		ВходящийКонтекст.Вставить("Пароль", РезультатВызова.Результат);
		ВходящийКонтекст.НастройкиПользователя.Пароль = РезультатВызова.Результат;
		
		ПараметрыПодтверждения = Новый Структура();
		ПараметрыПодтверждения.Вставить("ИдентификаторТранзакции", "");
		ПараметрыПодтверждения.Вставить("ТипПодтверждения", "Аутентификация");
		ПараметрыПодтверждения.Вставить("ЗаголовокФормы", НСтр("ru = 'Подтвердите аутентификацию'", КодЯзыка()));
		
		ПодтвердитьОперацию(ВходящийКонтекст.НастройкиПользователя,
							ОповещениеСледующее,
							ПараметрыПодтверждения);
		
	Иначе
		АутентификацияДвухФакторнаяРезультат(РезультатВызова, ВходящийКонтекст);
	КонецЕсли;	

КонецПроцедуры

// Продолжение процедуры АутентификацияДвухФакторная.
Процедура АутентификацияДвухФакторнаяПослеВыполнения(РезультатВызова, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(РезультатВызова, ВходящийКонтекст);
	ПродолжитьАвторизацию = Ложь;
		
	Если РезультатВыполнения.Выполнено = Истина Тогда
		НастройкиПользователя = РезультатВыполнения.НастройкиПользователя;
		РезультатВыполнения.МаркерОбновлен = Истина;
		Если ВходящийКонтекст.Сохранить Тогда
			СохранитьЗакрытыеДанные(НастройкиПользователя.УникальныйИдентификатор, ВходящийКонтекст.Пароль, "Пароль");
		КонецЕсли;
		
		Если НЕ НастройкиПользователя.Политика.Заполнено Тогда
			ОбъектОповещения	= Новый ОписаниеОповещения("АутентификацияДвухФакторнаяПослеОбновленияПолитики", ЭтотОбъект);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			НачатьЗамерВремени(ВходящийКонтекст);
		
			ПараметрыОперации = ВходящийКонтекст.ПараметрыОперации;
			ПодключитьФормуОжидания(ПараметрыОперации, Истина);
			
			ОжидатьЗавершенияВыполненияВФоне(
				ОповещениеСледующее, 
				СервисКриптографииDSSСлужебныйВызовСервера.ОбновитьПолитикуПользователя(
						ВходящийКонтекст.НастройкиПользователя,
						ПараметрыОперации),
				ПараметрыОперации);
			ПродолжитьАвторизацию = Истина;
		КонецЕсли;
		
	Иначе
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		
	КонецЕсли;	
	ИзменитьСчетчикПопыток(НастройкиПользователя, РезультатВыполнения.Выполнено);
	
	Если СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) 
		И НЕ НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ОбъектОповещения	= Новый ОписаниеОповещения("АутентификацияДвухФакторнаяЗапросПароля", ЭтотОбъект);
		ОповещениеСледующее	= ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ОтобразитьОшибкуПользователю(ОповещениеСледующее, РезультатВыполнения.Ошибка, , ВходящийКонтекст.ПараметрыОперации);
	ИначеЕсли НЕ ПродолжитьАвторизацию Тогда
		РезультатВыполнения.МаркерОбновлен = Истина;
		РезультатВыполнения.Вставить("НастройкиПользователя", НастройкиПользователя);
		АутентификацияДвухФакторнаяРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;

КонецПроцедуры

// Продолжение процедуры АутентификацияДвухФакторная.
Процедура АутентификацияДвухФакторнаяПослеОбновленияПолитики(РезультатВызова, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(РезультатВызова, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		РезультатВыполнения.МаркерОбновлен = Истина;
		НовыеНастройки = РезультатВыполнения.НастройкиПользователя;
		ПроверитьТокенНаОбновление(РезультатВыполнения, ВходящийКонтекст.НастройкиПользователя);
		СервисКриптографииDSSСлужебныйВызовСервера.ОбновитьНастройкиПользователя(ВходящийКонтекст.НастройкиПользователя, НовыеНастройки);
	КонецЕсли;
	
	АутентификацияДвухФакторнаяРезультат(РезультатВыполнения, ВходящийКонтекст);
	
КонецПроцедуры

// Продолжение процедуры АутентификацияДвухФакторная.
Процедура АутентификацияДвухФакторнаяРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область АутентификацияЧерезВебФорму

// Запускает цикл авторизации через web-форму
// Данный вариант возможно использовать, если в настройках DSS включен режим: 
// "Методы первичной аутентификации: Аутентификация по паролю" или 
// "Методы первичной аутентификации: Только идентификация"
//
// Шаги цикла:
// 1. подготовка параметров цикла авторизации
// 2. открытие и ожидание ввода в web-форме
// 3. получение результата аутентификации в форме
// 4. сохранение нового токена для сеанса, возврат в случае успеха новых настроек пользователя.
//
Процедура АутентификацияЧерезВебФорму(НастройкиПользователя, ОповещениеОЗавершении, ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыВызова			= Новый Структура();
	ПараметрыВызова.Вставить("ВидОперации", НСтр("ru = 'Авторизация интерактивная'", КодЯзыка()));
	ПараметрыВызова.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыВызова.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыВызова.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	Если ИспользованиеОблачнойПодписиВозможно(ПараметрыВызова) Тогда
		ОбъектОповещения	= Новый ОписаниеОповещения("АутентификацияЧерезВебФормуПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыВызова);
		
		ОткрытьФормуВебАутентификации(НастройкиПользователя, ОповещениеСледующее, ПараметрыВызова.ПараметрыОперации);
	КонецЕсли;	

КонецПроцедуры

// Продолжение процедуры АутентификацияЧерезВебФорму.
Процедура АутентификацияЧерезВебФормуПослеВыполнения(РезультатВызова, ВходящийКонтекст) Экспорт
	
	Если РезультатВызова.Выполнено Тогда
		НастройкиПользователя = РезультатВызова.НастройкиПользователя;
		ИзменитьСчетчикПопыток(НастройкиПользователя, Истина);
		СервисКриптографииDSSСлужебныйВызовСервера.ОбновитьНастройкиПользователя(
								НастройкиПользователя, 
								НастройкиПользователя,
								ВходящийКонтекст.ПараметрыОперации);
		РезультатВызова.МаркерОбновлен = Истина;
		РезультатВызова.Вставить("НастройкиПользователя", НастройкиПользователя);
	Иначе
		ИзменитьСчетчикПопыток(ВходящийКонтекст.НастройкиПользователя, Ложь);
	КонецЕсли;	
	
	АутентификацияЧерезВебФормуРезультат(РезультатВызова, ВходящийКонтекст);
	
КонецПроцедуры

// Продолжение процедуры АутентификацияЧерезВебФорму.
Процедура АутентификацияЧерезВебФормуРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область ПроверкаВыбранногоПользователя

// Запускает цикл проверки выбранной учетной записи
//
// Шаги цикла:
// 1. подготовка параметров цикла проверки
// 2. если учетная запись не передана в параметрах вызова, то пользователю предлагается самостоятельно выбрать 
// 3. возврат в случае успеха настроек выбранного пользователя.
//
Процедура ПроверкаВыбранногоПользователя(ОповещениеОЗавершении, НастройкиПользователя, ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Проверка выбранного пользователя'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	СписокУчетныхЗаписей = СвойствоСтруктуры(ПараметрыОперации, "СписокУчетныхЗаписей", Новый Массив);
	ПоказатьСписок = СвойствоСтруктуры(ПараметрыОперации, "ПоказатьСписок", Ложь);
		
	Если ИспользованиеОблачнойПодписиВозможно(ПараметрыЦикла) Тогда
		ВыбранПользователь = Неопределено;
		Если СписокУчетныхЗаписей.Количество() = 1 Тогда 
			ВыбранПользователь = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьНастройкиПользователя(СписокУчетныхЗаписей[0], ПараметрыОперации);
			ПараметрыЦикла.НастройкиПользователя = ВыбранПользователь;
		ИначеЕсли НастройкиПользователя = Неопределено 
			ИЛИ НЕ ЗначениеЗаполнено(НастройкиПользователя.Логин) Тогда
			СписокУчетныхЗаписей = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьВсеУчетныеЗаписи();
			Если СписокУчетныхЗаписей.Количество() = 1 И НЕ ПоказатьСписок Тогда
				ВыбранПользователь = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьНастройкиПользователя(СписокУчетныхЗаписей[0], ПараметрыОперации);
				ПараметрыЦикла.НастройкиПользователя = ВыбранПользователь;
			КонецЕсли;
		Иначе
			ВыбранПользователь = НастройкиПользователя;
		КонецЕсли;
		
		Если ВыбранПользователь = Неопределено Тогда
			ПроверкаВыбранногоПользователяВыборИзСписка(ПараметрыЦикла);
		Иначе
			ПроверкаВыбранногоПользователяРезультат(ОтветСервисаПоУмолчанию(), ПараметрыЦикла);
		КонецЕсли;
		
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПроверкаВыбранногоПользователя.
Процедура ПроверкаВыбранногоПользователяВыборИзСписка(ВходящийКонтекст)
	
	ОбъектОповещения	= Новый ОписаниеОповещения("ПроверкаВыбранногоПользователяПослеВыбора", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		
	ОткрытьФормуВыбораУчетнойЗаписи(ОповещениеСледующее, ВходящийКонтекст.ПараметрыОперации);
	
КонецПроцедуры

// Продолжение процедуры ПроверкаВыбранногоПользователя.
Процедура ПроверкаВыбранногоПользователяПослеВыбора(РезультатВыбора, ВходящийКонтекст) Экспорт
	
	Если РезультатВыбора.Выполнено Тогда
		ВходящийКонтекст.НастройкиПользователя = РезультатВыбора.Результат;
	КонецЕсли;
	
	ПроверкаВыбранногоПользователяРезультат(РезультатВыбора, ВходящийКонтекст);
		
КонецПроцедуры

// Продолжение процедуры ПроверкаВыбранногоПользователя.
Процедура ПроверкаВыбранногоПользователяРезультат(РезультатВыполнения, ВходящийКонтекст)
	
	Если РезультатВыполнения.Выполнено Тогда
		РезультатВыполнения.Вставить("Результат", ВходящийКонтекст.НастройкиПользователя);
	КонецЕсли;
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВыполнения);
	
КонецПроцедуры

#КонецОбласти

#Область ПроверкаАутентификацииПользователя

// Продолжение процедуры ПроверкаАутентификацииПользователяПослеВыбора.
Функция ТокенАвторизацииУстарел(НастройкиПользователя)
	
	Результат = Неопределено;
	
	Если НЕ ТребуетсяВводКонфиденциальныхДанных(НастройкиПользователя.ТокенАвторизации.Токен) Тогда
		ДатаСеанса = ДатаСеанса();
		Если НЕ ТребуетсяВводКонфиденциальныхДанных(НастройкиПользователя.ТокенАвторизации.ТокенОбновления) Тогда
			Результат = Ложь;
		ИначеЕсли НастройкиПользователя.ТокенАвторизации.СрокДействия > ДатаСеанса Тогда
			Результат = Ложь;
		Иначе
			Результат = Истина;
		КонецЕсли;	
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Запускает цикл проверки валидности токена подключения для учетной записи
// Служебный цикл, в основном предназначен для запуска из других циклов
//
// Шаги цикла:
// 1. подготовка параметров цикла проверки
// 2. выбор учетной записи в случае необходимости
// 3. сохранение нового токена для сеанса, возврат в случае успеха новых настроек пользователя, 
//	  если после выбора аутентификация прошла успешно.
//
Процедура ПроверкаАутентификацииПользователя(ОповещениеОЗавершении, ВходящийКонтекст, ЭтоОшибка = Ложь, Принудительно = Ложь) Экспорт
	
	НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
	
	Если ВходящийКонтекст.Свойство("ПараметрыОперации") Тогда
		ВходящиеПараметры = ПроверитьПараметрыОперации(ВходящийКонтекст.ПараметрыОперации);
	Иначе
		ВходящиеПараметры = ПроверитьПараметрыОперации(Неопределено);
	КонецЕсли;	
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Проверка авторизации пользователя'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ВходящийКонтекст", ВходящийКонтекст);
	ПараметрыЦикла.Вставить("Принудительно", Принудительно);
	ПараметрыЦикла.Вставить("ЭтоОшибка", ЭтоОшибка);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ВходящиеПараметры);
	
	Если ИспользованиеОблачнойПодписиВозможно(ВходящийКонтекст) Тогда
		ОбъектОповещения	= Новый ОписаниеОповещения("ПроверкаАутентификацииПользователяПослеВыбора", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
		ПроверкаВыбранногоПользователя(ОповещениеСледующее, НастройкиПользователя, ВходящиеПараметры);
	КонецЕсли;
	
КонецПроцедуры

// Служит для максимизации процесса выбора подходящей учетной записи без интерактивного выбора
// Параметры:
//  ОповещениеОЗавершении - ОписаниеОповещения - указывает процедуру для получения результата операции. 
//  ВходящийКонтекст - Структура
//  Отбор - Соответствие - поиск подходящей учетной записи
// 	
Процедура ПроверкаАутентификацииПользователяСОтбором(ОповещениеОЗавершении, ВходящийКонтекст, Отбор)
	
	НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
	
	Если ВходящийКонтекст.Свойство("ПараметрыОперации") Тогда
		ВходящиеПараметры = ПроверитьПараметрыОперации(ВходящийКонтекст.ПараметрыОперации);
	Иначе
		ВходящиеПараметры = ПроверитьПараметрыОперации(Неопределено);
	КонецЕсли;	
	
	НашлиНастройки = Новый Массив;
	Если НастройкиПользователя = Неопределено Тогда 
		ВсеНастройки = СервисКриптографииDSSСлужебныйВызовСервера.ПодобратьНастройкиПользователя(Отбор, ВходящиеПараметры);
		Если ВсеНастройки.Количество() = 1 Тогда
			НастройкиПользователя = СервисКриптографииDSSКлиент.ПолучитьНастройкиПользователя(ВсеНастройки[0], ВходящиеПараметры);
		ИначеЕсли ВсеНастройки.Количество() > 0 Тогда
			НашлиНастройки = ВсеНастройки;
		КонецЕсли;
	КонецЕсли;
	
	ВходящиеПараметры.Вставить("СписокУчетныхЗаписей", НашлиНастройки);
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Проверка авторизации пользователя'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ВходящийКонтекст", ВходящийКонтекст);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ВходящиеПараметры);
	ПараметрыЦикла.Вставить("Принудительно", Ложь);
	ПараметрыЦикла.Вставить("ЭтоОшибка", Ложь);
	
	ОбъектОповещения	= Новый ОписаниеОповещения("ПроверкаАутентификацииПользователяПослеВыбора", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаВыбранногоПользователя(ОповещениеСледующее, НастройкиПользователя, ВходящиеПараметры);

КонецПроцедуры

// Продолжение процедуры ПроверкаАутентификацииПользователя.
Процедура ПроверкаАутентификацииПользователяПослеВыбора(РезультатВызова, ВходящийКонтекст) Экспорт
	
	Если РезультатВызова.Выполнено Тогда
		НастройкиПользователя = РезультатВызова.Результат;
		ВходящийКонтекст.ВходящийКонтекст.НастройкиПользователя = НастройкиПользователя;
		ВходящийКонтекст.НастройкиПользователя = НастройкиПользователя;
		ВидАутентификации = НастройкиПользователя.ПервичнаяАутентификация;
		ПарольПользователя = СвойствоСтруктуры(ВходящийКонтекст.ПараметрыОперации, "ПарольПользователя");
		
		ВызватьДиалог			= Ложь;
		ВызватьФоновоеЗадание	= Ложь;
		ЭтоОшибка				= ВходящийКонтекст.ЭтоОшибка;
		Принудительно			= ВходящийКонтекст.Принудительно;
		ТокенУстарел			= ТокенАвторизацииУстарел(НастройкиПользователя);
		
		Если ПарольПользователя <> Неопределено Тогда
			ТекущийПароль = ПарольПользователя;
		ИначеЕсли ВидАутентификации = ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_СертификатАвторизации") Тогда
			ТекущийПароль = НастройкиПользователя.ПарольСертификата;
		Иначе
			ТекущийПароль = НастройкиПользователя.Пароль;
		КонецЕсли;
		
		ПустойПароль = ТребуетсяВводКонфиденциальныхДанных(ТекущийПароль);
		
		Если Принудительно Тогда
			ВызватьФоновоеЗадание = Истина;
			Если ВидАутентификации = ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_ДвухФакторная") Тогда 
				ВызватьДиалог = Истина;
			ИначеЕсли ВидАутентификации = ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_КодАвторизации") Тогда
				ВызватьДиалог = Истина;
			ИначеЕсли ВидАутентификации = ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_СертификатАвторизации") Тогда
				ВызватьДиалог = ПустойПароль;
			ИначеЕсли ВидАутентификации = ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_УчетныеДанные") Тогда
				ВызватьДиалог = ПустойПароль;
			КонецЕсли;	
		Иначе	
			Если ТокенУстарел = Неопределено Тогда
				ВызватьФоновоеЗадание = Истина;
			КонецЕсли;	
			
			Если ТокенУстарел <> Ложь ИЛИ ЭтоОшибка Тогда
				Если ЭтоОшибка Тогда
					НастройкиПользователя.Пароль = СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 3);
					НастройкиПользователя.ПарольСертификата = СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 3);
				КонецЕсли;
				
				Если ВидАутентификации = ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_ДвухФакторная") Тогда 
					КлючДействия = СервисКриптографииDSSКлиентСервер.СвойствоВыполняемойОперации(НастройкиПользователя, "ВыпускМаркера");
					ВызватьДиалог = ПустойПароль ИЛИ ЭтоОшибка ИЛИ КлючДействия.Подтверждать;
					ВызватьФоновоеЗадание = НЕ ВызватьДиалог;
				ИначеЕсли ВидАутентификации = ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_КодАвторизации") Тогда
					ВызватьДиалог = Истина;
					ВызватьФоновоеЗадание = Ложь;
				ИначеЕсли ВидАутентификации = ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_СертификатАвторизации") Тогда
					ВызватьДиалог = ПустойПароль ИЛИ ЭтоОшибка;
					ВызватьФоновоеЗадание = НЕ ВызватьДиалог;
				ИначеЕсли ВидАутентификации = ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_УчетныеДанные") Тогда
					ВызватьДиалог = ПустойПароль ИЛИ ЭтоОшибка;
					ВызватьФоновоеЗадание = НЕ ВызватьДиалог;
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;	
		
		Если ВызватьДиалог Тогда
			ПроверкаАутентификацииПользователяОткрытьФорму(Неопределено, ВходящийКонтекст);
		ИначеЕсли ВызватьФоновоеЗадание Тогда
			ПроверкаАутентификацииПользователяФоновымЗаданием(Неопределено, ВходящийКонтекст);
		Иначе	
			РезультатВызова = ОтветСервисаПоУмолчанию();
			РезультатВызова.Вставить("НастройкиПользователя", НастройкиПользователя);
			ПроверкаАутентификацииПользователяРезультат(РезультатВызова, ВходящийКонтекст);
		КонецЕсли;
		
	Иначе
		ПроверкаАутентификацииПользователяРезультат(РезультатВызова, ВходящийКонтекст);
		
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПроверкаАутентификацииПользователя.
Процедура ПроверкаАутентификацииПользователяФоновымЗаданием(РезультатВызова, ВходящийКонтекст)
	
	НастройкиПользователя	= ВходящийКонтекст.НастройкиПользователя;
	ВидАутентификации 		= НастройкиПользователя.ПервичнаяАутентификация;
	
	ОбъектОповещения	= Новый ОписаниеОповещения("ПроверкаАутентификацииПользователяПослеВыполнения", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	НачатьЗамерВремени(ВходящийКонтекст);
		
	Если ВидАутентификации = ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_СертификатАвторизации") Тогда
		НоваяОперация = СервисКриптографииDSSСлужебныйВызовСервера.АутентификацияПоСертификату(НастройкиПользователя);
	Иначе		
		НоваяОперация = СервисКриптографииDSSСлужебныйВызовСервера.АутентификацияПоЛогину(НастройкиПользователя);
	КонецЕсли;
				
	ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, НоваяОперация, ВходящийКонтекст.ПараметрыОперации);
	
КонецПроцедуры

// Продолжение процедуры ПроверкаАутентификацииПользователя.
Процедура ПроверкаАутентификацииПользователяОткрытьФорму(РезультатВызова, ВходящийКонтекст)
	
	ОбъектОповещения	= Новый ОписаниеОповещения("ПроверкаАутентификацииПользователяРезультат", ЭтотОбъект);
	ОписаниеСледующее	= ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	
	НастройкиПользователя	= ВходящийКонтекст.НастройкиПользователя;
	ВидАутентификации 		= НастройкиПользователя.ПервичнаяАутентификация;
	ПараметрыОперации		= ПроверитьПараметрыОперации(ВходящийКонтекст.ПараметрыОперации);
	ДатаСеанса 				= ДатаСеанса();
	Авторизован 			= СервисКриптографииDSSКлиентСервер.УчетнаяЗаписьАвторизована(НастройкиПользователя, ДатаСеанса);
	
	Если НЕ Авторизован Тогда
		ПодключитьФормуОжидания(ПараметрыОперации, Истина);
	КонецЕсли;
	
	Если ВидАутентификации = ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_ДвухФакторная") Тогда
		АутентификацияДвухФакторная(НастройкиПользователя, ОписаниеСледующее, ПараметрыОперации);
	ИначеЕсли ВидАутентификации = ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_КодАвторизации") Тогда
		АутентификацияЧерезВебФорму(НастройкиПользователя, ОписаниеСледующее, ПараметрыОперации);
	ИначеЕсли ВидАутентификации = ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_СертификатАвторизации") Тогда
		АутентификацияПоСертификату(НастройкиПользователя, ОписаниеСледующее, ПараметрыОперации);
	ИначеЕсли ВидАутентификации = ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_УчетныеДанные") Тогда
		АутентификацияПоЛогину(НастройкиПользователя, ОписаниеСледующее, ПараметрыОперации);
	Иначе
		ОтветПользователю = ОтветСервисаПоУмолчанию(Ложь);
		СформироватьОтказАутентификации(ОтветПользователю);
		ПроверкаАутентификацииПользователяРезультат(ОтветПользователю, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПроверкаАутентификацииПользователя.
Процедура ПроверкаАутентификацииПользователяПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		РезультатВыполнения.МаркерОбновлен = Истина;
		ПроверитьТокенНаОбновление(РезультатВыполнения, ВходящийКонтекст.НастройкиПользователя);
	КонецЕсли;
	
	ПроверкаАутентификацииПользователяРезультат(РезультатВыполнения, ВходящийКонтекст);
	
КонецПроцедуры

// Продолжение процедуры ПроверкаАутентификацииПользователя.
Процедура ПроверкаАутентификацииПользователяРезультат(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВыполнения);
	
КонецПроцедуры

#КонецОбласти

#Область ПодтверждениеПроизвольнойОперации

// Запускает цикл для процесса произвольного подтверждения
// Данный вариант возможно использовать, если в настройках DSS используется хотя бы один 
// вариант вторичного подтверждения 
//
// Шаги цикла подтверждения:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. разветвление, если в настройках указан шаблон, то пункт 6, иначе будет запущено фиктивное подписание
// 4. поиск подходящего сертификата (не требующий ввода пин-кода)
// 5. запуск вложенного процесса создания транзакции
// 6. запуск вложенного процесса подтверждения
// 7. ожидание результата транзакции (для фиктивного подписания)
// 8. проверка успешности окончания операции, если пароль неправильный, то цикл запускает заново (3)
// 9. сохранение нового токена для сеанса, возврат в случае успеха новых настроек пользователя.
//
Процедура ПодтверждениеПроизвольнойОперации(НастройкиПользователя, ОповещениеОЗавершении, СодержаниеОперации = "", СпособПодтверждения = Неопределено, ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла		= Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Подтверждение произвольной операции'", КодЯзыка()));
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("СодержаниеОперации", СодержаниеОперации);
	ПараметрыЦикла.Вставить("ШаблонПодтверждения", "");
	ПараметрыЦикла.Вставить("КодОперации", 0);
	ПараметрыЦикла.Вставить("СпособПодтверждения", СпособПодтверждения);
	ПараметрыЦикла.Вставить("ЕстьШаблон", ЗначениеЗаполнено(НастройкиПользователя.ШаблонПодтверждения));
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения	= Новый ОписаниеОповещения("ПодтверждениеПроизвольнойОперацииНачало", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
	
КонецПроцедуры

// Продолжение процедуры ПодтверждениеПроизвольнойОперации.
Процедура ПодтверждениеПроизвольнойОперацииНачало(РезультатВызова, ВходящийКонтекст) Экспорт
	
	Если РезультатВызова.Выполнено Тогда
		КлючДействия = КлючДействияОперации("ПодписьДокумента", ВходящийКонтекст.НастройкиПользователя);
		ВходящийКонтекст.ШаблонПодтверждения = ВходящийКонтекст.НастройкиПользователя.ШаблонПодтверждения;
		ВходящийКонтекст.КодОперации = КлючДействия.КодОперации;
		
		Если ВходящийКонтекст.ЕстьШаблон Тогда
			ОбъектОповещения = Новый ОписаниеОповещения("ПодтверждениеПроизвольнойОперацииОжидать", ЭтотОбъект);
		Иначе 
			// Делаем через подписание произвольной информации, при этом должны быть зарегистрированы сертификаты
			ОбъектОповещения = Новый ОписаниеОповещения("ПодтверждениеПроизвольнойОперацииСертификат", ЭтотОбъект);
		КонецЕсли;	
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ВыполнитьОбработкуОповещения(ОповещениеСледующее, ОтветСервисаПоУмолчанию());
	Иначе
		ПодтверждениеПроизвольнойОперацииРезультат(РезультатВызова, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПодтверждениеПроизвольнойОперации.
Процедура ПодтверждениеПроизвольнойОперацииСертификат(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		
		НастройкиПользователя	= ВходящийКонтекст.НастройкиПользователя;
		ТекущийСертификат		= СервисКриптографииDSSКлиентСервер.НайтиСертификат(НастройкиПользователя, "Любой");
		
		Если НЕ ЗначениеЗаполнено(ТекущийСертификат.Отпечаток) Тогда
			ОтветСервиса = ОтветСервисаПоУмолчанию(Ложь);
			ПолучитьОписаниеОшибки(ОтветСервиса, "СертификатыНеОбнаружены");
			ПодтверждениеПроизвольнойОперацииРезультат(РезультатВыполнения, ВходящийКонтекст);
		Иначе
			ВходящийКонтекст.Вставить("Сертификат", ТекущийСертификат);
			ПодтверждениеПроизвольнойОперацииСоздатьТранзакцию(РезультатВыполнения, ВходящийКонтекст);
		КонецЕсли;
		
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ПодтверждениеПроизвольнойОперацииРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения	= Новый ОписаниеОповещения("ПодтверждениеПроизвольнойОперацииНачало", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
		
	Иначе
		ПодтверждениеПроизвольнойОперацииРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	КонецЕсли;	

КонецПроцедуры

// Продолжение процедуры ПодтверждениеПроизвольнойОперации.
//
// Параметры:
//   РезультатВыполнения	- Структура
//  ВходящийКонтекст 	- Структура:
//    * Сертификат	- см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//
Процедура ПодтверждениеПроизвольнойОперацииСоздатьТранзакцию(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		ВерсияПодтверждения = СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
		
		ОбъектОповещения	= Новый ОписаниеОповещения("ПодтверждениеПроизвольнойОперацииОжидать", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			
		СвойствоПодписи = СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиCMS(Истина, Ложь);
		СервисКриптографииDSSКлиентСервер.ПолучитьИнформациюДокументаДляПодписи(СвойствоПодписи, ВходящийКонтекст.СодержаниеОперации, "txt");
		
		Если ВерсияПодтверждения = 2 Тогда
			ПараметрыОперации = ОбщегоНазначенияКлиент.СкопироватьРекурсивно(ВходящийКонтекст.ПараметрыОперации);
			ПараметрыОперации.Вставить("ПодтверждатьПринудительно", Истина);
			
			ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.ПодписатьАсинхронно(
					ВходящийКонтекст.НастройкиПользователя,
					ПолучитьДвоичныеДанныеИзСтроки(ВходящийКонтекст.СодержаниеОперации),
					СвойствоПодписи,
					ВходящийКонтекст.Сертификат.Идентификатор, 
					ВходящийКонтекст.Сертификат.ПинКод, 
					ПараметрыОперации);
			
		Иначе
			СвойствоПодписи = СервисКриптографииDSSКлиентСервер.СвойстваТранзакцииПодписания(СвойствоПодписи, ВходящийКонтекст.Сертификат.Идентификатор);
			ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.СоздатьТранзакцию(
						ВходящийКонтекст.НастройкиПользователя,
						СвойствоПодписи, 
						ВходящийКонтекст.КодОперации, 
						ПолучитьДвоичныеДанныеИзСтроки(ВходящийКонтекст.СодержаниеОперации));
		КонецЕсли;
			
		ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, ОбработкаОперации, ВходящийКонтекст.ПараметрыОперации);
				
	Иначе
		ПодтверждениеПроизвольнойОперацииРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры ПодтверждениеПроизвольнойОперации.
Процедура ПодтверждениеПроизвольнойОперацииОжидать(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ПроверитьТокенНаОбновление(РезультатВыполнения, ВходящийКонтекст.НастройкиПользователя);
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		ВерсияПодтверждения = СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);

		Если ВходящийКонтекст.ЕстьШаблон Тогда
			ОбъектОповещения = Новый ОписаниеОповещения("ПодтверждениеПроизвольнойОперацииПослеВыполнения", ЭтотОбъект);
		Иначе
			ОбъектОповещения = Новый ОписаниеОповещения("ПодтверждениеПроизвольнойОперацииФоновымЗаданием", ЭтотОбъект);
		КонецЕсли;
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		
		ПараметрыПодтверждения = Новый Структура();
		ПараметрыПодтверждения.Вставить("ТипПодтверждения", "ПроизвольнаяОперация");
		ПараметрыПодтверждения.Вставить("ЗаголовокФормы", ВходящийКонтекст.СодержаниеОперации);
		ПараметрыПодтверждения.Вставить("ШаблонПодтверждения", ВходящийКонтекст.ШаблонПодтверждения);
		ПараметрыПодтверждения.Вставить("СпособПодтверждения", ВходящийКонтекст.СпособПодтверждения);
		
		Если ВерсияПодтверждения = 2 Тогда
			ПараметрыПодтверждения.Вставить("ИдентификаторОперации", СвойствоСтруктуры(РезультатВыполнения, "Результат.ИдентификаторОперации", ""));
		Иначе	
			ПараметрыПодтверждения.Вставить("ИдентификаторТранзакции", СвойствоСтруктуры(РезультатВыполнения, "Результат", ""));
		КонецЕсли;
		
		ПодтвердитьОперацию(ВходящийКонтекст.НастройкиПользователя,
							ОповещениеСледующее,
							ПараметрыПодтверждения,
							ВходящийКонтекст.ПараметрыОперации);
							
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ПодтверждениеПроизвольнойОперацииРезультат(РезультатВыполнения, ВходящийКонтекст);
							
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПодтверждениеПроизвольнойОперацииСоздатьТранзакцию", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
		
	Иначе
		ПодтверждениеПроизвольнойОперацииРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли;
									
КонецПроцедуры	

// Продолжение процедуры ПодтверждениеПроизвольнойОперации.
// 
// Параметры:
//   РезультатВыполнения	- Структура
//  ВходящийКонтекст 	- Структура:
//    * Сертификат	- см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//
Процедура ПодтверждениеПроизвольнойОперацииФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		ВерсияПодтверждения = СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
		
		ОбъектОповещения = Новый ОписаниеОповещения("ПодтверждениеПроизвольнойОперацииПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		ВходящийКонтекст.НастройкиПользователя = РезультатВыполнения.НастройкиПользователя;
		ВходящийКонтекст.ПараметрыОперации.Вставить("Транзакция", Истина);
		ВходящийКонтекст.ПараметрыОперации.Вставить("ТипРезультата", "ДвоичныеДанные");
		
		Если ВерсияПодтверждения = 2 Тогда
			ПараметрыОперации	= ОбщегоНазначенияКлиент.СкопироватьРекурсивно(ВходящийКонтекст.ПараметрыОперации);
			ПараметрыОперации.Вставить("ПодтверждатьПринудительно", Истина);
			
			ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.ПодписатьАсинхронно(
					ВходящийКонтекст.НастройкиПользователя,
					Неопределено,
					Неопределено,
					ВходящийКонтекст.Сертификат.Идентификатор, 
					ВходящийКонтекст.Сертификат.ПинКод, 
					ПараметрыОперации);
		Иначе
			ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.Подписать(
					ВходящийКонтекст.НастройкиПользователя,
					Неопределено, 
					Неопределено, 
					ВходящийКонтекст.Сертификат.Идентификатор, 
					ВходящийКонтекст.Сертификат.ПинКод, 
					Ложь,
					ВходящийКонтекст.ПараметрыОперации);
		КонецЕсли;
		
		ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, ОбработкаОперации, ВходящийКонтекст.ПараметрыОперации);
		
	Иначе
		ПодтверждениеПроизвольнойОперацииРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры ПодтверждениеПроизвольнойОперации.
Процедура ПодтверждениеПроизвольнойОперацииПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ПодтверждениеПроизвольнойОперацииРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ПодтверждениеПроизвольнойОперацииРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаПинКода(РезультатВыполнения.Ошибка) Тогда // неверный пин-код
		ПодтверждениеПроизвольнойОперацииРезультат(ОтветСервисаПоУмолчанию(Истина), ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПодтверждениеПроизвольнойОперацииНачало", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		ПодтверждениеПроизвольнойОперацииРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПодтверждениеПроизвольнойОперации.
Процедура ПодтверждениеПроизвольнойОперацииРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область Зашифровать

// Запускает цикл для процесса шифрования
//
// Шаги цикла шифрования:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. запуск фонового задания для шифрования
// 4. проверка успешности окончания операции
// 5. сохранение нового токена для сеанса, возврат результата шифрования.
//
Процедура Зашифровать(НастройкиПользователя, 
			ОповещениеОЗавершении, 
			ДанныеДокумента, 
			СертификатыПолучателей, 
			ТипШифрования = "CMS", 
			ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Зашифрование данных'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ДанныеДокумента", ДанныеДокумента);
	ПараметрыЦикла.Вставить("СертификатыПолучателей", СертификатыПолучателей);
	ПараметрыЦикла.Вставить("ТипШифрования", ТипШифрования);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ЗашифроватьФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	Если НастройкиПользователя = Неопределено Тогда
		ПроверкаАутентификацииПользователяСОтбором(ОповещениеСледующее, ПараметрыЦикла, Неопределено);
	Иначе	
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла, Ложь);
	КонецЕсли;	

КонецПроцедуры	

// Продолжение процедуры Зашифровать.
Процедура ЗашифроватьФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		ВерсияПодтверждения = СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
		
		ОбъектОповещения = Новый ОписаниеОповещения("ЗашифроватьПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		Если ВерсияПодтверждения = 2 Тогда
			ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.ЗашифроватьАсинхронно(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ДанныеДокумента, 
						ВходящийКонтекст.СертификатыПолучателей, 
						ВходящийКонтекст.ТипШифрования,
						ВходящийКонтекст.ПараметрыОперации);
		Иначе		
			ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.Зашифровать(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ДанныеДокумента, 
						ВходящийКонтекст.СертификатыПолучателей, 
						ВходящийКонтекст.ТипШифрования,
						ВходящийКонтекст.ПараметрыОперации);
		КонецЕсли;
					
			
		ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, ОбработкаОперации, ВходящийКонтекст.ПараметрыОперации);
		
	Иначе
		ЗашифроватьРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры Зашифровать.
Процедура ЗашифроватьПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ЗашифроватьРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ЗашифроватьРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ЗашифроватьФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		ЗашифроватьРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры Зашифровать.
Процедура ЗашифроватьРезультат(РезультатВызова, ВходящийКонтекст)
	
	ПодготовленныйРезультат = ПодготовитьПсевдонимыОтвета(РезультатВызова, ВходящийКонтекст.ПараметрыОперации);
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова, ПодготовленныйРезультат);
	
КонецПроцедуры

#КонецОбласти

#Область Расшифровать

// Запускает цикл для процесса расшифровки
//
// Шаги цикла авторизации:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. извлечение серийных номеров из сообщения и поиск идентификатора сертификата
// 4. если предыдущий пункт не получился, то получение сервисом из свойств шифрованных 
//	  данных списка сертификатов учетной записи
// 5. проверка пин-кода для выбранного сертификата
// 6. проверка необходимости подтверждения, если нужно запуск вложенного процесса создания транзакции
// 7. расшифровка данных фоновым заданием
// 8. проверка результат операции, если ошибка авторизации, то цикл повторяется 
// 9. сохранение нового токена для сеанса, возврат результата расшифровки.
//
Процедура Расшифровать(НастройкиПользователя, 
			ОповещениеОЗавершении, 
			ДанныеДокумента, 
			ТипШифрования = "CMS",
			Сертификат = Неопределено,
			ПараметрыОперации = Неопределено) Экспорт
			
	ИдентификаторТранзакции	= СвойствоСтруктуры(ПараметрыОперации, "ИдентификаторТранзакции", "");
	ПинКод	= СвойствоСтруктуры(ПараметрыОперации, "ПинКод");
	ЗапомнитьПинКод	= СвойствоСтруктуры(ПараметрыОперации, "ЗапомнитьПинКод", Ложь);
	ПодтверждатьПринудительно = СвойствоСтруктуры(ПараметрыОперации, "ПодтверждатьПринудительно", Ложь);
	ТипРезультата = СвойствоСтруктуры(ПараметрыОперации, "ТипРезультата", "Неопределено");
	
	Если ТипРезультата = "Неопределено" Тогда
		ТипРезультата = СервисКриптографииDSSКлиентСервер.ПолучитьТипДанныхДокумента(ДанныеДокумента);
	КонецЕсли;
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Расшифрование данных'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ДанныеДокумента", ДанныеДокумента);
	ПараметрыЦикла.Вставить("ТипШифрования", ТипШифрования);
	ПараметрыЦикла.Вставить("ИнформацияОДокументе", СвойствоСтруктуры(ПараметрыОперации, "ИнформацияОДокументе", "Расшифровка"));
	ПараметрыЦикла.Вставить("ТипДокумента", СвойствоСтруктуры(ПараметрыОперации, "ТипДокумента", "bin"));
	ПараметрыЦикла.Вставить("Сертификат", Сертификат);
	ПараметрыЦикла.Вставить("ИдентификаторТранзакции", ИдентификаторТранзакции);
	ПараметрыЦикла.Вставить("ПинКод", ПинКод);
	ПараметрыЦикла.Вставить("ЗапомнитьПинКод", ЗапомнитьПинКод);
	ПараметрыЦикла.Вставить("ТипРезультата", ТипРезультата);
	ПараметрыЦикла.Вставить("ПодтверждатьПринудительно", ПодтверждатьПринудительно);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("РасшифроватьПоСерийнымНомерам", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
			
КонецПроцедуры	

// Продолжение процедуры Расшифровать.
// Иногда сервис не может разобрать двоичные данные, получаем идентификатор сертификата альтернативным способом,
// также предварительная проверка позволяет не делать лишний запрос к сервису.
//
// Параметры:
//   РезультатВызова		- Структура
//  ВходящийКонтекст 	- Структура:
//    * НастройкиПользователя	- см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//
Процедура РасшифроватьПоСерийнымНомерам(РезультатВызова, ВходящийКонтекст) Экспорт
	
	Если РезультатВызова.Выполнено Тогда
		
		Если ВходящийКонтекст.Сертификат = Неопределено Тогда
			
			ДанныеДокумента = СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(ВходящийКонтекст.ДанныеДокумента, Истина);
			СерийныеНомера = СервисКриптографииDSSASNКлиентСервер.ПолучитьСертификатыШифрования(ДанныеДокумента.Документ);
			УчетнаяЗапись = ВходящийКонтекст.НастройкиПользователя.Ссылка;
			
			Для каждого СтрокаМассива Из СерийныеНомера Цикл
				НашлиСертификат = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьСертификатПоСерийномуНомеру(СтрокаМассива.СерийныйНомер);
				Если НашлиСертификат <> Неопределено И НашлиСертификат.УчетнаяЗапись = УчетнаяЗапись Тогда
					ВходящийКонтекст.Сертификат = Новый Структура("Отпечаток", НашлиСертификат.Отпечаток);
					Прервать;
				КонецЕсли;	
			КонецЦикла;
			
		КонецЕсли;	
		
		РасшифроватьПолучитьСертификаты(РезультатВызова, ВходящийКонтекст);
		
	Иначе
		РасшифроватьРезультат(РезультатВызова, ВходящийКонтекст);
		
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры Расшифровать.
Процедура РасшифроватьПолучитьСертификаты(РезультатВызова, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(РезультатВызова, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		ВерсияПодтверждения = СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
		
		Если ВходящийКонтекст.Сертификат = Неопределено Тогда
			ОбъектОповещения = Новый ОписаниеОповещения("РасшифроватьПроверитьПинКод", ЭтотОбъект);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			НачатьЗамерВремени(ВходящийКонтекст, "ВидОперации", "ПолучитьСертификатыРасшифрования");
			
			Если ВерсияПодтверждения = 2 Тогда
				НоваяОперация = СервисКриптографииDSSСлужебныйВызовСервера.СертификатыРасшифрованияАсинхронно(
							ВходящийКонтекст.НастройкиПользователя,
							ВходящийКонтекст.ДанныеДокумента, 
							ВходящийКонтекст.ТипШифрования, 
							ВходящийКонтекст.ПараметрыОперации);
			Иначе
				НоваяОперация = СервисКриптографииDSSСлужебныйВызовСервера.СертификатыРасшифрования(
							ВходящийКонтекст.НастройкиПользователя,
							ВходящийКонтекст.ДанныеДокумента, 
							ВходящийКонтекст.ТипШифрования, 
							ВходящийКонтекст.ПараметрыОперации);
			КонецЕсли;
						
			ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, НоваяОперация, ВходящийКонтекст.ПараметрыОперации);
				
		Иначе
			РезультатВызова = ОтветСервисаПоУмолчанию(Истина);
			РезультатВызова.Вставить("Результат", Новый Массив);
			НашлиСертификат = СервисКриптографииDSSКлиентСервер.НайтиСертификат(ВходящийКонтекст.НастройкиПользователя, ВходящийКонтекст.Сертификат);
			Если НашлиСертификат.Идентификатор <> -1 Тогда
				РезультатВызова.Результат.Добавить(НашлиСертификат.Идентификатор);
			КонецЕсли;
			РасшифроватьПроверитьПинКод(РезультатВызова, ВходящийКонтекст);
			
		КонецЕсли;
		
	Иначе
		РасшифроватьРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры Расшифровать.
// 
// Параметры:
//   ДлительнаяОперация	- Структура
//  ВходящийКонтекст 	- Структура:
//    * НастройкиПользователя	- см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//
Процедура РасшифроватьПроверитьПинКод(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		СписокСертификатов = НастройкиПользователя.Сертификаты;
		
		ПриоритетныйСертификат = Неопределено;
		Для каждого СтрокаКлюча Из СписокСертификатов Цикл
			ТекущийСертификат	= СтрокаКлюча.Значение;
			НашлиСертификат 	= РезультатВыполнения.Результат.Найти(ТекущийСертификат.Идентификатор);
			Если НашлиСертификат <> Неопределено
				И (ПриоритетныйСертификат = Неопределено 
				ИЛИ НЕ ТекущийСертификат.ТребуетсяПинКод 
				ИЛИ НЕ ТребуетсяВводКонфиденциальныхДанных(ТекущийСертификат.ПинКод)) Тогда
				ПриоритетныйСертификат = ТекущийСертификат; // СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя()
			КонецЕсли;
		КонецЦикла;
		
		Если ПриоритетныйСертификат <> Неопределено И ВходящийКонтекст.Сертификат = Неопределено Тогда
			ВходящийКонтекст.Сертификат = Новый Структура("Отпечаток", ПриоритетныйСертификат.Отпечаток);
		КонецЕсли;
		
		Если ПриоритетныйСертификат = Неопределено Тогда
			ОтветСервиса = ОтветСервисаПоУмолчанию(Ложь);
			ПолучитьОписаниеОшибки(ОтветСервиса, "СертификатыНеОбнаружены");
			РасшифроватьРезультат(ОтветСервиса, ВходящийКонтекст);
		ИначеЕсли ВходящийКонтекст.ПинКод <> Неопределено Тогда
			Если ВходящийКонтекст.ЗапомнитьПинКод Тогда
				УстановитьПинКодСертификата(ТекущийСертификат, НастройкиПользователя, ВходящийКонтекст.ПинКод, , , ВходящийКонтекст.ПараметрыОперации);
			КонецЕсли;
			ПриоритетныйСертификат.ПинКод = ВходящийКонтекст.ПинКод;
			РезультатВыполнения = ОтветСервисаПоУмолчанию();
			ВходящийКонтекст.Вставить("ОписаниеСертификата", ПриоритетныйСертификат);
			ВходящийКонтекст.Вставить("ПредставлениеСертификата", ПриоритетныйСертификат);
			РасшифроватьСоздатьТранзакцию(РезультатВыполнения, ВходящийКонтекст);
		Иначе
			ВходящийКонтекст.Вставить("ОписаниеСертификата", ПриоритетныйСертификат);
			ОбъектОповещения = Новый ОписаниеОповещения("РасшифроватьПослеВводаПинКода", ЭтотОбъект);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			ПинКодСертификата(НастройкиПользователя, ОповещениеСледующее, ПриоритетныйСертификат.Идентификатор, ВходящийКонтекст.ПараметрыОперации);
		КонецЕсли;
		
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		РасшифроватьРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("РасшифроватьПолучитьСертификаты", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
		
	Иначе
		РасшифроватьРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры Расшифровать.
Процедура РасшифроватьПослеВводаПинКода(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		Если РезультатВыполнения.Результат.ОбновилиПинКод Тогда
			ВходящийКонтекст.НастройкиПользователя = РезультатВыполнения.Результат.НастройкиПользователя;
		КонецЕсли;	
		РасшифроватьСоздатьТранзакцию(РезультатВыполнения, ВходящийКонтекст);
	Иначе
		РасшифроватьРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры Расшифровать.
// 
// Параметры:
//   ДлительнаяОперация	- Структура
//  ВходящийКонтекст 	- Структура:
//    * ОписаниеСертификата - см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//
Процедура РасшифроватьСоздатьТранзакцию(ДлительнаяОперация, ВходящийКонтекст)
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		ОписаниеСертификата	= ВходящийКонтекст.ОписаниеСертификата;
		ВерсияПодтверждения = СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
		КлючДействия = КлючДействияОперации("Расшифрование", НастройкиПользователя);
		ВходящийКонтекст.Вставить("Транзакция", КлючДействия.Подтверждать);
		
		Если ЗначениеЗаполнено(ВходящийКонтекст.ИдентификаторТранзакции) Тогда
			ПодтверждатьОперацию = Ложь;
			ВходящийКонтекст.Вставить("Транзакция", Истина);
		Иначе
			ПодтверждатьОперацию = КлючДействия.Подтверждать ИЛИ ВходящийКонтекст.ПодтверждатьПринудительно;
			ВходящийКонтекст.Вставить("Транзакция", ПодтверждатьОперацию);
		КонецЕсли;	
		
		Если ПодтверждатьОперацию И ВерсияПодтверждения = 2 Тогда
			ОбъектОповещения 	= Новый ОписаниеОповещения("РасшифроватьАсинхронноПодтверждение", ЭтотОбъект);
			СледующееОповещение = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			
			ПараметрыОперации	= ОбщегоНазначенияКлиент.СкопироватьРекурсивно(ВходящийКонтекст.ПараметрыОперации);
			ПараметрыОперации.Вставить("ПодтверждатьПринудительно", Истина);
			
			ОжидатьЗавершенияВыполненияВФоне(
				СледующееОповещение, 
				СервисКриптографииDSSСлужебныйВызовСервера.РасшифроватьАсинхронно(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ДанныеДокумента,
						ОписаниеСертификата.Идентификатор,
						ВходящийКонтекст.ТипШифрования,
						ОписаниеСертификата.ПинКод, 
						ПараметрыОперации),
				ВходящийКонтекст.ПараметрыОперации);
			
		ИначеЕсли ПодтверждатьОперацию Тогда
			ОбъектОповещения 		= Новый ОписаниеОповещения("РасшифроватьФоновымЗаданием", ЭтотОбъект);
			СледующееОповещение 	= ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			ПараметрыРасшифрования 	= СервисКриптографииDSSКлиентСервер.СвойстваТранзакцииРасшифрования(
						ВходящийКонтекст.ТипШифрования,
						ОписаниеСертификата.Идентификатор,
						ВходящийКонтекст.ТипДокумента,
						ВходящийКонтекст.ИнформацияОДокументе);
						
			СоздатьТранзакцию(НастройкиПользователя,
					СледующееОповещение,
					ПараметрыРасшифрования, 
					КлючДействия.КодОперации,
					НСтр("ru = 'Подтвердите расшифровку документа.'", КодЯзыка()),
					ВходящийКонтекст.ДанныеДокумента,
					ВходящийКонтекст.ПараметрыОперации);
		Иначе
			РасшифроватьФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст);
		КонецЕсли;
	Иначе
		РасшифроватьРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры Расшифровать.
Процедура РасшифроватьАсинхронноПодтверждение(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ВходящийКонтекст.ИдентификаторТранзакции = РезультатВыполнения.Результат.ИдентификаторОперации;
		
		ОбъектОповещения = Новый ОписаниеОповещения("РасшифроватьФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		
		ПараметрыПодтверждения = Новый Структура();
		ПараметрыПодтверждения.Вставить("ИдентификаторОперации", ВходящийКонтекст.ИдентификаторТранзакции);
		ПараметрыПодтверждения.Вставить("ЗаголовокФормы", НСтр("ru = 'Подтвердите расшифровку документа.'", КодЯзыка()));
		ПараметрыПодтверждения.Вставить("ТипПодтверждения", "Транзакция");
		
		ПодтвердитьОперацию(ВходящийКонтекст.НастройкиПользователя, ОповещениеСледующее, ПараметрыПодтверждения, ВходящийКонтекст.ПараметрыОперации);
		
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ПодписатьРезультат(РезультатВыполнения, ВходящийКонтекст);			
	Иначе
		ПодписатьРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры Расшифровать.
// 
// Параметры:
//   РезультатВыполнения	- Структура
//  ВходящийКонтекст 	- Структура:
//    * ОписаниеСертификата - см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//
Процедура РасшифроватьФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	ПроверитьТокенНаОбновление(РезультатВыполнения, ВходящийКонтекст.НастройкиПользователя);
	Если РезультатВыполнения.Выполнено Тогда
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		ВерсияПодтверждения = СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
		ОписаниеСертификата = ВходящийКонтекст.ОписаниеСертификата;
		
		ОбъектОповещения = Новый ОписаниеОповещения("РасшифроватьПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст, "ВидОперации", "Расшифрование");
			
		ОписаниеСертификата = ВходящийКонтекст.ОписаниеСертификата;
		ВходящийКонтекст.ПараметрыОперации.Вставить("Транзакция", ВходящийКонтекст.Транзакция);
		
		Если ВходящийКонтекст.Транзакция И ЗначениеЗаполнено(ВходящийКонтекст.ИдентификаторТранзакции) Тогда
			ТрансформацияДанных(ВходящийКонтекст.ПараметрыОперации, ВходящийКонтекст.ТипРезультата);
		ИначеЕсли ВходящийКонтекст.Транзакция Тогда
			ТрансформацияДанных(ВходящийКонтекст.ПараметрыОперации, РезультатВыполнения.ТрансформироватьРезультат);
		КонецЕсли;
		
		Если ВерсияПодтверждения = 2 Тогда
			НоваяОперация = СервисКриптографииDSSСлужебныйВызовСервера.РасшифроватьАсинхронно(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ДанныеДокумента,
						ОписаниеСертификата.Идентификатор,
						ВходящийКонтекст.ТипШифрования,
						ОписаниеСертификата.ПинКод,
						ВходящийКонтекст.ПараметрыОперации);
		Иначе
			НоваяОперация = СервисКриптографииDSSСлужебныйВызовСервера.Расшифровать(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ДанныеДокумента,
						ОписаниеСертификата.Идентификатор,
						ВходящийКонтекст.ТипШифрования,
						ОписаниеСертификата.ПинКод,
						ВходящийКонтекст.ПараметрыОперации);
		КонецЕсли;
					
		ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, НоваяОперация, ВходящийКонтекст.ПараметрыОперации);
					
	Иначе
		РасшифроватьРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры Расшифровать.
Процедура РасшифроватьПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		РезультатВыполнения.Вставить("Сертификат", ВходящийКонтекст.Сертификат);
		РасшифроватьРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		РасшифроватьРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("РасшифроватьФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		РасшифроватьРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры Расшифровать.
Процедура РасшифроватьРезультат(РезультатВызова, ВходящийКонтекст)
	
	ПодготовленныйРезультат = ПодготовитьПсевдонимыОтвета(РезультатВызова, ВходящийКонтекст.ПараметрыОперации);
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова, ПодготовленныйРезультат);
	
КонецПроцедуры

#КонецОбласти

#Область РасшифроватьВЦикле

// Запускает расшифровку перебором всех учетных записей , состоящей из этапов
//
// Шаги цикла авторизации:
// 1. подготовка параметров цикла
// 2. делается попытка извлечь серийные номера сертификатов, если не удается, то второй пункт
// 3. в цикле перебирает учетные записи и запускает вложенный процесс расшифровки
// 4. сохранение нового токена для сеансов, возврат результата шифрования.
//
Процедура РасшифроватьВЦикле(ОповещениеОЗавершении, 
			ДанныеДокумента, 
			ТипШифрования = "CMS", 
			ПараметрыОперации = Неопределено) Экспорт
			
	ПараметрыЦикла 	= Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Расшифрование данных по учетным записям'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("СчетчикМассива", 0);
	ПараметрыЦикла.Вставить("ДанныеДокумента", ДанныеДокумента);
	ПараметрыЦикла.Вставить("ТипШифрования", ТипШифрования);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	ПараметрыЦикла.Вставить("ИнформацияОДокументе", СвойствоСтруктуры(ПараметрыОперации, "ИнформацияОДокументе", "Расшифровка"));
	ПараметрыЦикла.Вставить("ТипДокумента", СвойствоСтруктуры(ПараметрыОперации, "ТипДокумента", "txt"));
	ПараметрыЦикла.Вставить("РасшифровкаПоУчетнымЗаписям", СвойствоСтруктуры(ПараметрыОперации, "РасшифровкаПоУчетнымЗаписям", Ложь));
	
	Если ИспользованиеОблачнойПодписиВозможно(ПараметрыЦикла) Тогда
		РасшифроватьВЦиклеПоСерийнымНомерам(ОтветСервисаПоУмолчанию(Ложь), ПараметрыЦикла);
	КонецЕсли;	
			
КонецПроцедуры	

// Продолжение процедуры РасшифроватьВЦикле.
Процедура РасшифроватьВЦиклеПоСерийнымНомерам(РезультатВызова, ВходящийКонтекст)
	
	ДанныеДокумента = СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(ВходящийКонтекст.ДанныеДокумента, Истина);
	СерийныеНомера = СервисКриптографииDSSASNКлиентСервер.ПолучитьСертификатыШифрования(ДанныеДокумента.Документ);
	МассивЗаписей = Новый Массив;
	
	Если СерийныеНомера.Количество() > 0 Тогда
		МассивНомеров = Новый Массив;
		Для каждого СтрокаМассива Из СерийныеНомера Цикл
			МассивНомеров.Добавить(СтрокаМассива.СерийныйНомер);
		КонецЦикла;
		ДанныеСертификатов = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьСертификатПоСерийномуНомеру(Новый Структура("СерийныйНомер", МассивНомеров));
		
		Если ДанныеСертификатов <> Неопределено Тогда
			Если ДанныеСертификатов.Количество() = 1 Тогда
				ТекущийСертификат = ДанныеСертификатов[0];
				НастройкиПользователя = СервисКриптографииDSSКлиент.ПолучитьНастройкиПользователя(ТекущийСертификат.УчетнаяЗапись, ВходящийКонтекст.ПараметрыОперации);
				Расшифровать(НастройкиПользователя,
						ВходящийКонтекст.ОповещениеОЗавершении,
						ВходящийКонтекст.ДанныеДокумента,
						ВходящийКонтекст.ТипШифрования,
						ТекущийСертификат, 
						ВходящийКонтекст.ПараметрыОперации);
				Возврат;
			ИначеЕсли ДанныеСертификатов.Количество() > 1 Тогда
				ВходящийКонтекст.РасшифровкаПоУчетнымЗаписям = Истина;
				Для каждого СтрокаМассива Из ДанныеСертификатов Цикл
					ДополнитьМассивУчетныхЗаписей(МассивЗаписей, СтрокаМассива.УчетнаяЗапись);
				КонецЦикла;
			КонецЕсли;	
		КонецЕсли;
		
	КонецЕсли;
	
	Если МассивЗаписей.Количество() = 0 
		И ВходящийКонтекст.РасшифровкаПоУчетнымЗаписям Тогда
		ВсеНастройки	= СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьУчетныеЗаписи();
		Для каждого СтрокаМассива Из ВсеНастройки Цикл
			ДополнитьМассивУчетныхЗаписей(МассивЗаписей, СтрокаМассива);
		КонецЦикла;
	КонецЕсли;	
		
	ВходящийКонтекст.Вставить("СписокУчетныхЗаписей", МассивЗаписей);
	
	РасшифроватьВЦиклеСледующаяУчетнаяЗапись(Неопределено, ВходящийКонтекст);
	
КонецПроцедуры

// Продолжение процедуры РасшифроватьВЦикле.
Процедура РасшифроватьВЦиклеСледующаяУчетнаяЗапись(РезультатВызова, ВходящийКонтекст) Экспорт
	
	Счетчик = ВходящийКонтекст.СчетчикМассива;
	
	Если РезультатВызова <> Неопределено Тогда
		ВходящийКонтекст.СписокУчетныхЗаписей[Счетчик - 1].Результат = РезультатВызова;
	КонецЕсли;
	
 	СписокУчетныхЗаписей = ВходящийКонтекст.СписокУчетныхЗаписей;
	
	Если РезультатВызова = Неопределено ИЛИ НЕ РезультатВызова.Выполнено Тогда
		
		ПродолжитьРаботу = Истина;
		Если СписокУчетныхЗаписей.Количество() = 0 Тогда
			ПродолжитьРаботу = Ложь;
		ИначеЕсли НЕ СписокУчетныхЗаписей.Количество() > Счетчик Тогда
			ПродолжитьРаботу = Ложь;
		КонецЕсли;
		
		Если ПродолжитьРаботу Тогда
			НастройкиПользователя = СервисКриптографииDSSКлиент.ПолучитьНастройкиПользователя(
										СписокУчетныхЗаписей[Счетчик].УчетнаяЗапись, 
										ВходящийКонтекст.ПараметрыОперации);
			ВходящийКонтекст.Вставить("НастройкиПользователя", НастройкиПользователя);
			ВходящийКонтекст.СчетчикМассива = Счетчик + 1;
			
			ОбъектОповещения = Новый ОписаниеОповещения("РасшифроватьВЦиклеСледующаяУчетнаяЗапись", ЭтотОбъект);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
				
			Расшифровать(НастройкиПользователя, 
				ОповещениеСледующее, 
				ВходящийКонтекст.ДанныеДокумента,
				ВходящийКонтекст.ТипШифрования,
				,
				ВходящийКонтекст.ПараметрыОперации);
			
		Иначе
			
			МассивОшибок = Новый Массив;
			// соберем все ошибки
			Для Каждого СтрокаМассива Из СписокУчетныхЗаписей Цикл
				Если МассивОшибок.Количество() = 0 Тогда
					МассивОшибок.Добавить(СтрокаМассива.Результат.Ошибка);
				ИначеЕсли СервисКриптографииDSSКлиентСервер.ПолучитьКодОшибки(СтрокаМассива.Результат.Ошибка) = "100002" Тогда
					МассивОшибок.Вставить(0, СтрокаМассива.Результат.Ошибка);
				ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаОтказа(СтрокаМассива.Результат.Ошибка) Тогда
					МассивОшибок.Вставить(1, СтрокаМассива.Результат.Ошибка);
				Иначе
					МассивОшибок.Добавить(СтрокаМассива.Результат.Ошибка);
				КонецЕсли;	
			КонецЦикла;
			
			РезультатСОшибкой = ОтветСервисаПоУмолчанию(Ложь, "РасшифровкаВЦикле");
			Если МассивОшибок.Количество() = 0 И РезультатВызова <> Неопределено Тогда
				ПолучитьОписаниеОшибки(РезультатСОшибкой, "РасшифровкаВЦикле", РезультатВызова.Ошибка);
			Иначе	
				РезультатСОшибкой.Ошибка = СтрСоединить(МассивОшибок, Символы.ПС);
			КонецЕсли;
			
			РасшифроватьВЦиклеРезультат(РезультатСОшибкой, ВходящийКонтекст);
		КонецЕсли;
	Иначе
		РасшифроватьВЦиклеРезультат(РезультатВызова, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры РасшифроватьВЦикле.
Процедура РасшифроватьВЦиклеРезультат(РезультатВызова, ВходящийКонтекст)
	
	ПодготовленныйРезультат = ПодготовитьПсевдонимыОтвета(РезультатВызова, ВходящийКонтекст.ПараметрыОперации);
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова, ПодготовленныйРезультат);
	
КонецПроцедуры

// Продолжение процедуры РасшифроватьВЦикле.
Процедура ДополнитьМассивУчетныхЗаписей(МассивЗаписей, УчетнаяЗапись)
	
	ЕстьЗапись = Ложь;
	Для Каждого СтрокаМассива Из МассивЗаписей Цикл
		Если СтрокаМассива.УчетнаяЗапись = УчетнаяЗапись Тогда
			ЕстьЗапись = Истина;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	
	Если НЕ ЕстьЗапись Тогда
		НоваяСтрока = Новый Структура("УчетнаяЗапись, Результат", УчетнаяЗапись, ОтветСервисаПоУмолчанию(Ложь));
		МассивЗаписей.Добавить(НоваяСтрока);
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область ХешированиеДанных

// Запускает цикл хеширования документа
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. запуск фонового задания для хеширования
// 4. проверка успешности окончания операции
// 5. сохранение нового токена для сеанса, возврат результата хеширования.
//
Процедура ХешированиеДанных(НастройкиПользователя, 
			ОповещениеОЗавершении, 
			ДанныеДокумента, 
			АлгоритмХеширования,
			ПараметрыОперации) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Вычисление значение хеша'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ДанныеДокумента", ДанныеДокумента);
	ПараметрыЦикла.Вставить("АлгоритмХеширования", АлгоритмХеширования);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ХешированиеДанныхФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла, Ложь);
	
КонецПроцедуры	

// Продолжение процедуры ХешированиеДанных.
Процедура ХешированиеДанныхФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ХешированиеДанныхПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		ОжидатьЗавершенияВыполненияВФоне(
			ОповещениеСледующее, 
			СервисКриптографииDSSСлужебныйВызовСервера.ХешированиеДанных(
					ВходящийКонтекст.НастройкиПользователя,
					ВходящийКонтекст.ДанныеДокумента, 
					ВходящийКонтекст.АлгоритмХеширования, 
					ВходящийКонтекст.ПараметрыОперации),
		ВходящийКонтекст.ПараметрыОперации);
	Иначе
		ХешированиеДанныхРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;				
	
КонецПроцедуры

// Продолжение процедуры ХешированиеДанных.
Процедура ХешированиеДанныхПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ХешированиеДанныхРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ХешированиеДанныхРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ХешированиеДанныхФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		ХешированиеДанныхРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ХешированиеДанных.
Процедура ХешированиеДанныхРезультат(РезультатВызова, ВходящийКонтекст)
	
	ПодготовленныйРезультат = ПодготовитьПсевдонимыОтвета(РезультатВызова, ВходящийКонтекст.ПараметрыОперации);
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова, ПодготовленныйРезультат);
	
КонецПроцедуры

#КонецОбласти

#Область Подписать

// Запускает цикл подписи одиночного документа или пакета документов
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. проверка переданного сертификата на наличие в сервисе
// 4. проверка необходимости ввод пин-кода и ввода его, вложенный процесс
// 5. проверка необходимости подтверждения, запуск вложенного процесса транзакции
// 6. подписание данных через фоновое задание
// 7. сохранение нового токена для сеанса, возврат результата подписания.
//
Процедура Подписать(НастройкиПользователя,
				ОповещениеОЗавершении,
				ДанныеДокумента,
				СвойствоПодписи,
				Сертификат = Неопределено,
				ПараметрыОперации = Неопределено) Экспорт
				
	ПакетнаяПодпись = ТипЗнч(ДанныеДокумента) = Тип("Массив");
	ПоточнаяПодпись	= СвойствоСтруктуры(ПараметрыОперации, "ПотоковыйРежим", Ложь);
	ИдентификаторТранзакции	= СвойствоСтруктуры(ПараметрыОперации, "ИдентификаторТранзакции", "");
	ПинКод = СвойствоСтруктуры(ПараметрыОперации, "ПинКод");
	ЗапомнитьПинКод	= СвойствоСтруктуры(ПараметрыОперации, "ЗапомнитьПинКод", Ложь);
	ПодтверждатьПринудительно = СвойствоСтруктуры(ПараметрыОперации, "ПодтверждатьПринудительно", Ложь);
	ПакетнаяОперация = СвойствоСтруктуры(ПараметрыОперации, "ПакетнаяПодпись", Ложь);
	ТипРезультата = СвойствоСтруктуры(ПараметрыОперации, "ТипРезультата", "Неопределено");
	
	Если ТипРезультата = "Неопределено" Тогда
		ТипРезультата = СервисКриптографииDSSКлиентСервер.ПолучитьТипДанныхДокумента(ДанныеДокумента);
	КонецЕсли;
	
	Если ПакетнаяПодпись Тогда
		ПоточнаяПодпись = Ложь;
	КонецЕсли;	
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Подписание данных'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ДанныеДокумента", ДанныеДокумента);
	ПараметрыЦикла.Вставить("СвойствоПодписи", СвойствоПодписи);
	ПараметрыЦикла.Вставить("Сертификат", Сертификат);
	ПараметрыЦикла.Вставить("ПакетнаяПодпись", ПакетнаяПодпись ИЛИ ПакетнаяОперация);
	ПараметрыЦикла.Вставить("ПотоковыйРежим", ПоточнаяПодпись);
	ПараметрыЦикла.Вставить("ИдентификаторТранзакции", ИдентификаторТранзакции);
	ПараметрыЦикла.Вставить("ПинКод", ПинКод);
	ПараметрыЦикла.Вставить("ЗапомнитьПинКод", ЗапомнитьПинКод);
	ПараметрыЦикла.Вставить("ТипРезультата", ТипРезультата);
	ПараметрыЦикла.Вставить("ПодтверждатьПринудительно", ПодтверждатьПринудительно);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	ПараметрыЦикла.Вставить("ПакетнаяОперация", ПакетнаяОперация);
	ПараметрыЦикла.Вставить("ПредставлениеСертификата", "");
	ПараметрыЦикла.Вставить("ЭтоПакет", ПакетнаяПодпись ИЛИ ПакетнаяОперация);
	
	ОбъектОповещения = Новый ОписаниеОповещения("ПодписатьПолучитьСертификат", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла, Ложь);
	
КонецПроцедуры

// Продолжение процедуры Подписать.
Процедура ПодписатьПолучитьСертификат(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		НастройкиПользователя = РезультатВыполнения.НастройкиПользователя;
		ВходящийКонтекст.НастройкиПользователя = НастройкиПользователя;
		
		Если НастройкиПользователя.Политика.ТипыПодписей.Найти(ВходящийКонтекст.СвойствоПодписи.SignatureType) = Неопределено Тогда
			РезультатВыполнения = ОтветСервисаПоУмолчанию(Ложь);
			ПолучитьОписаниеОшибки(РезультатВыполнения,
								"ТипПодписи", 
								НСтр("ru = 'Тип подписи:'", КодЯзыка()) + " "
								+ ВходящийКонтекст.СвойствоПодписи.SignatureType);
			ПодписатьРезультат(РезультатВыполнения, ВходящийКонтекст);
			
		Иначе
			ТекущийСертификат = СервисКриптографииDSSКлиентСервер.НайтиСертификат(ВходящийКонтекст.НастройкиПользователя, ВходящийКонтекст.Сертификат);
			
			Если НЕ ЗначениеЗаполнено(ТекущийСертификат.Отпечаток) Тогда
				РезультатОтвета = ОтветСервисаПоУмолчанию(Ложь);
				ПолучитьОписаниеОшибки(РезультатОтвета,
									"certificate_not_found", 
									НСтр("ru = 'При подписании'", КодЯзыка()));
				ПодписатьРезультат(РезультатОтвета, ВходящийКонтекст);
				
			ИначеЕсли ВходящийКонтекст.ПинКод <> Неопределено Тогда
				Если ВходящийКонтекст.ЗапомнитьПинКод Тогда
					УстановитьПинКодСертификата(ТекущийСертификат, НастройкиПользователя, ВходящийКонтекст.ПинКод, , , ВходящийКонтекст.ПараметрыОперации);
				КонецЕсли;
				ТекущийСертификат.ПинКод = ВходящийКонтекст.ПинКод;
				РезультатВыполнения = ОтветСервисаПоУмолчанию();
				ВходящийКонтекст.Вставить("ОписаниеСертификата", ТекущийСертификат);
				ВходящийКонтекст.Вставить("ПредставлениеСертификата", ТекущийСертификат);
				ПодписатьСоздатьТранзакцию(РезультатВыполнения, ВходящийКонтекст);
				
			Иначе	
				ВходящийКонтекст.Вставить("ОписаниеСертификата", ТекущийСертификат);
				ВходящийКонтекст.Вставить("ПредставлениеСертификата", ТекущийСертификат);
				ОбъектОповещения = Новый ОписаниеОповещения("ПодписатьПослеВводаПинКода", ЭтотОбъект);
				ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
				ПинКодСертификата(ВходящийКонтекст.НастройкиПользователя, ОповещениеСледующее, ТекущийСертификат.Идентификатор, ВходящийКонтекст.ПараметрыОперации);
				
			КонецЕсли;
		КонецЕсли;	
		
	Иначе
		ПодписатьРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры Подписать.
Процедура ПодписатьПослеВводаПинКода(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		Если РезультатВыполнения.Результат.ОбновилиПинКод Тогда
			ВходящийКонтекст.НастройкиПользователя = РезультатВыполнения.Результат.НастройкиПользователя;
		КонецЕсли;	
		ПодписатьСоздатьТранзакцию(РезультатВыполнения, ВходящийКонтекст);
	Иначе
		ПодписатьРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры Подписать.
//
// Параметры:
//   РезультатВыполнения	- Структура
//  ВходящийКонтекст 	- Структура:
//    * ОписаниеСертификата - см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//
Процедура ПодписатьСоздатьТранзакцию(РезультатВыполнения, ВходящийКонтекст)
	
	Если РезультатВыполнения.Выполнено Тогда
		НастройкиПользователя 	= ВходящийКонтекст.НастройкиПользователя;
		ВерсияПодтверждения = СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
		
		Если ВходящийКонтекст.ПакетнаяПодпись И ВерсияПодтверждения = 1 Тогда
			КлючДействия = КлючДействияОперации("ПодписьПакета", НастройкиПользователя);
		Иначе	
			КлючДействия = КлючДействияОперации("ПодписьДокумента", НастройкиПользователя);
 		КонецЕсли;
		
		Если ЗначениеЗаполнено(ВходящийКонтекст.ИдентификаторТранзакции) Тогда
			ПодтверждатьОперацию = Ложь;
			ВходящийКонтекст.Вставить("Транзакция", Истина);
		Иначе
			ПодтверждатьОперацию = КлючДействия.Подтверждать ИЛИ ВходящийКонтекст.ПодтверждатьПринудительно;
			ВходящийКонтекст.Вставить("Транзакция", ПодтверждатьОперацию);
		КонецЕсли;	
		
		ОписаниеСертификата = ВходящийКонтекст.ОписаниеСертификата;
		
		Если ПодтверждатьОперацию И ВерсияПодтверждения = 2 Тогда
			ОбъектОповещения 	= Новый ОписаниеОповещения("ПодписатьАсинхронноПодтверждение", ЭтотОбъект);
			СледующееОповещение = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			
			ПараметрыОперации = ОбщегоНазначенияКлиент.СкопироватьРекурсивно(ВходящийКонтекст.ПараметрыОперации); // Структура
			ПараметрыОперации.Вставить("Сертификат", ВходящийКонтекст.ПредставлениеСертификата);
			ПараметрыОперации.Вставить("ПодтверждатьПринудительно", Истина);
			
			ОжидатьЗавершенияВыполненияВФоне(
				СледующееОповещение, 
				СервисКриптографииDSSСлужебныйВызовСервера.ПодписатьАсинхронно(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ДанныеДокумента,
						ВходящийКонтекст.СвойствоПодписи,
						ОписаниеСертификата.Идентификатор, 
						ОписаниеСертификата.ПинКод, 
						ПараметрыОперации),
				ВходящийКонтекст.ПараметрыОперации);
			
		ИначеЕсли ПодтверждатьОперацию Тогда
			ОбъектОповещения 	= Новый ОписаниеОповещения("ПодписатьФоновымЗаданием", ЭтотОбъект);
			СледующееОповещение = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			ОписаниеСертификата = ВходящийКонтекст.ОписаниеСертификата;
			СвойствоПодписи		= СервисКриптографииDSSКлиентСервер.СвойстваТранзакцииПодписания(
				ВходящийКонтекст.СвойствоПодписи, ОписаниеСертификата.Идентификатор);
			
			ПараметрыОперации = ОбщегоНазначенияКлиент.СкопироватьРекурсивно(ВходящийКонтекст.ПараметрыОперации); // Структура
			ПараметрыОперации.Вставить("Сертификат", ВходящийКонтекст.ПредставлениеСертификата);
						
			СоздатьТранзакцию(НастройкиПользователя,
					СледующееОповещение,
					СвойствоПодписи, 
					КлючДействия.КодОперации,
					НСтр("ru = 'Подтвердите подписание данных'", КодЯзыка()),
					ВходящийКонтекст.ДанныеДокумента,
					ПараметрыОперации);
		Иначе
			ПодписатьФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст);
		КонецЕсли;
	Иначе
		ПодписатьРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры Подписать.
Процедура ПодписатьАсинхронноПодтверждение(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ВходящийКонтекст.ИдентификаторТранзакции = РезультатВыполнения.Результат.ИдентификаторОперации;
		
		ОбъектОповещения = Новый ОписаниеОповещения("ПодписатьФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		
		ПараметрыПодтверждения = Новый Структура();
		ПараметрыПодтверждения.Вставить("ИдентификаторОперации", ВходящийКонтекст.ИдентификаторТранзакции);
		ПараметрыПодтверждения.Вставить("ЗаголовокФормы", НСтр("ru = 'Подтвердите подписание данных'", КодЯзыка()));
		ПараметрыПодтверждения.Вставить("ТипПодтверждения", "Транзакция");
		
		ПодтвердитьОперацию(ВходящийКонтекст.НастройкиПользователя, ОповещениеСледующее, ПараметрыПодтверждения, ВходящийКонтекст.ПараметрыОперации);
		
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ПодписатьРезультат(РезультатВыполнения, ВходящийКонтекст);			
	Иначе
		ПодписатьРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры Подписать.
// 
// Параметры:
//   РезультатВыполнения	- Структура
//  ВходящийКонтекст 	- Структура:
//    * ОписаниеСертификата - см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//
Процедура ПодписатьФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		ВерсияПодтверждения = СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
		ОписаниеСертификата = ВходящийКонтекст.ОписаниеСертификата;
		
		ОбъектОповещения = Новый ОписаниеОповещения("ПодписатьПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		ЭтоПакет = ВходящийКонтекст.ЭтоПакет;
		ВходящийКонтекст.ПараметрыОперации.Вставить("Транзакция", ВходящийКонтекст.Транзакция);
		ВходящийКонтекст.ПараметрыОперации.Вставить("ЭтоПакет", ВходящийКонтекст.ЭтоПакет);
		
		Если ВходящийКонтекст.Транзакция И ЗначениеЗаполнено(ВходящийКонтекст.ИдентификаторТранзакции) Тогда
			ТрансформацияДанных(ВходящийКонтекст.ПараметрыОперации, ВходящийКонтекст.ТипРезультата);
		ИначеЕсли ВходящийКонтекст.Транзакция Тогда
			ТрансформацияДанных(ВходящийКонтекст.ПараметрыОперации, РезультатВыполнения.ТрансформироватьРезультат);
		КонецЕсли;
		
		Если ВерсияПодтверждения = 2 Тогда
			ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.ПодписатьАсинхронно(
					ВходящийКонтекст.НастройкиПользователя,
					ВходящийКонтекст.ДанныеДокумента,
					ВходящийКонтекст.СвойствоПодписи,
					ОписаниеСертификата.Идентификатор, 
					ОписаниеСертификата.ПинКод, 
					ВходящийКонтекст.ПараметрыОперации);
			
		ИначеЕсли ЭтоПакет Тогда
			ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.ПодписатьПакет(
					ВходящийКонтекст.НастройкиПользователя,
					ВходящийКонтекст.ДанныеДокумента, 
					ВходящийКонтекст.СвойствоПодписи, 
					ОписаниеСертификата.Идентификатор, 
					ОписаниеСертификата.ПинКод, 
					ВходящийКонтекст.ПараметрыОперации);
					
		Иначе
			ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.Подписать(
					ВходящийКонтекст.НастройкиПользователя, 
					ВходящийКонтекст.ДанныеДокумента, 
					ВходящийКонтекст.СвойствоПодписи, 
					ОписаниеСертификата.Идентификатор, 
					ОписаниеСертификата.ПинКод, 
					ВходящийКонтекст.ПотоковыйРежим,
					ВходящийКонтекст.ПараметрыОперации)
		КонецЕсли;
		
		ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, ОбработкаОперации, ВходящийКонтекст.ПараметрыОперации);
		
	Иначе
		ПодписатьРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры Подписать.
Процедура ПодписатьПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ПодписатьРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ПодписатьРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПодписатьФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		ПодписатьРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры Подписать.
Процедура ПодписатьРезультат(РезультатВызова, ВходящийКонтекст)
	
	ПодготовленныйРезультат = ПодготовитьПсевдонимыОтвета(РезультатВызова, ВходящийКонтекст.ПараметрыОперации);
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова, ПодготовленныйРезультат);
	
КонецПроцедуры

#КонецОбласти

#Область УсовершенствоватьПодпись

// Запускает цикл для процесса усовершенствования подписи
//
// Шаги цикла шифрования:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. запуск фонового задания для шифрования
// 4. проверка успешности окончания операции
// 5. сохранение нового токена для сеанса, возврат результата усовершенствования подписи.
//
Процедура УсовершенствоватьПодпись(НастройкиПользователя, 
			ОповещениеОЗавершении, 
			ДанныеПодписи, 
			СвойствоПодписи,
			ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Усовершенствовать подпись'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ДанныеПодписи", ДанныеПодписи);
	ПараметрыЦикла.Вставить("СвойствоПодписи", СвойствоПодписи);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("УсовершенствоватьПодписьФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	Если НастройкиПользователя = Неопределено Тогда
		ПроверкаАутентификацииПользователяСОтбором(ОповещениеСледующее, ПараметрыЦикла, Неопределено);
	Иначе	
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла, Ложь);
	КонецЕсли;	

КонецПроцедуры	

// Продолжение процедуры УсовершенствоватьПодпись.
Процедура УсовершенствоватьПодписьФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		
		СписокСерверов = СервисКриптографииDSSКлиентСервер.ПолучитьСервераШтамповВремени(НастройкиПользователя);
		Если СписокСерверов.Количество() = 0 Тогда
			РезультатВыполнения = ОтветСервисаПоУмолчанию(Ложь);
			ПолучитьОписаниеОшибки(РезультатВыполнения,
								"ТипПодписи", 
								НСтр("ru = 'Не обнаружены зарегистрированные сервисы штампов времени.'", КодЯзыка()));
			УсовершенствоватьПодписьРезультат(РезультатВыполнения, ВходящийКонтекст);
		Иначе
			ОбъектОповещения = Новый ОписаниеОповещения("УсовершенствоватьПодписьПослеВыполнения", ЭтотОбъект);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			НачатьЗамерВремени(ВходящийКонтекст);
				
			ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.УсовершенствоватьПодпись(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ДанныеПодписи, 
						ВходящийКонтекст.СвойствоПодписи,
						ВходящийКонтекст.ПараметрыОперации);
				
			ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, ОбработкаОперации, ВходящийКонтекст.ПараметрыОперации);
		КонецЕсли;
		
	Иначе
		УсовершенствоватьПодписьРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры УсовершенствоватьПодпись.
Процедура УсовершенствоватьПодписьПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		УсовершенствоватьПодписьРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		УсовершенствоватьПодписьРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("УсовершенствоватьПодписьФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		УсовершенствоватьПодписьРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры УсовершенствоватьПодпись.
Процедура УсовершенствоватьПодписьРезультат(РезультатВызова, ВходящийКонтекст)
	
	ПодготовленныйРезультат = ПодготовитьПсевдонимыОтвета(РезультатВызова, ВходящийКонтекст.ПараметрыОперации);
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова, ПодготовленныйРезультат);
	
КонецПроцедуры

#КонецОбласти

#Область ПодготовитьТранзакцию

// Запускает цикл универсальной процедуры начала криптографической операции с сертификатом облачной подписи
// Особенность: отключена интерактивное взаимодействие с пользователем
//
// Шаги цикла фонового задания:
// 1. подготовка параметров цикла
// 2. авторизация, по необходимости
// 3. проверка пин-кода (для шифрования не требуется)
// 4. проверка сертификата и его даты действия
// 5. создание транзакция (только для Подписание, Расшифрование)
// 6. сохранение нового токена для сеанса и идентификатора транзакции.
//
Процедура ПодготовитьТранзакцию(ОповещениеОЗавершении, ПараметрыВыполнения, ПараметрыОперации) Экспорт
	
	ДополнимПараметры = ПроверитьПараметрыОперации(ПараметрыОперации);
	ДополнимПараметры.Вставить("ОтобразитьОшибку", Ложь);
	ПодключитьФормуОжидания(ДополнимПараметры, Истина);
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Подготовка транзакции'", КодЯзыка()));
	ПараметрыЦикла.Вставить("НастройкиПользователя", ПараметрыВыполнения.НастройкиПользователя);
	ПараметрыЦикла.Вставить("ПараметрыВыполнения", ПроверитьПараметрыОперации(ПараметрыВыполнения));
	ПараметрыЦикла.Вставить("ПараметрыОперации", ДополнимПараметры);
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	
	Если НЕ ИспользованиеОблачнойПодписиВозможно(ПараметрыЦикла) Тогда
		Возврат;
	КонецЕсли;
	
	ОбъектОповещения = Новый ОписаниеОповещения("ПодготовитьТранзакциюФоновоеЗадание", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	
	Если ТребуетсяВводКонфиденциальныхДанных(ПараметрыВыполнения.ПарольПользователя) Тогда
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
	Иначе
		ВыполнитьОбработкуОповещения(ОповещениеСледующее, ОтветСервисаПоУмолчанию());
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПодготовитьТранзакцию.
Процедура ПодготовитьТранзакциюФоновоеЗадание(РезультатВызова, ВходящийКонтекст) Экспорт
	
	Если РезультатВызова.Выполнено Тогда
		ПроверитьТокенНаОбновление(РезультатВызова, ВходящийКонтекст.НастройкиПользователя);
		ОбъектОповещения = Новый ОписаниеОповещения("ПодготовитьТранзакциюПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
		
		ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.ПодготовитьТранзакцию(
				ВходящийКонтекст.НастройкиПользователя,
				ВходящийКонтекст.ПараметрыВыполнения,
				ВходящийКонтекст.ПараметрыОперации);
		
		ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, ОбработкаОперации, ВходящийКонтекст.ПараметрыОперации);
	Иначе
		ПодготовитьТранзакциюРезультат(РезультатВызова, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПодготовитьТранзакцию.
Процедура ПодготовитьТранзакциюПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	ПодготовитьТранзакциюРезультат(РезультатВыполнения, ВходящийКонтекст);
	
КонецПроцедуры

// Продолжение процедуры ПодготовитьТранзакцию.
Процедура ПодготовитьТранзакциюРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры	
	
#КонецОбласти

#Область СоздатьТранзакцию

// Вспомогательный процесс для операций требующих подтверждения
// Может быть задействован при:
//	- подпись
//	- расшифровка
//	- создание запроса на сертификат
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. создание транзакции фоновым заданием, передачей данных для нее 
// 4. запуск вложенного процесса подтверждения операции
// 5. проверка необходимости подтверждения, запуск вложенного процесса транзакции
// 6. сохранение нового токена для сеанса, возврат результата подтверждения.
//
Процедура СоздатьТранзакцию(НастройкиПользователя, 
			ОповещениеОЗавершении, 
			ДанныеЗапроса,
			КодОперации,
			ОписаниеОперации,
			ДанныеДокумента = Неопределено,
			ПараметрыОперации = Неопределено)
			
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Создание транзакции:'", КодЯзыка()) + " " + КодОперации);
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ДанныеДокумента", ДанныеДокумента);
	ПараметрыЦикла.Вставить("ДанныеЗапроса", ДанныеЗапроса);
	ПараметрыЦикла.Вставить("КодОперации", КодОперации);
	ПараметрыЦикла.Вставить("ОписаниеОперации", ОписаниеОперации);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("СоздатьТранзакциюФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
	
КонецПроцедуры

// Продолжение процедуры СоздатьТранзакцию.
Процедура СоздатьТранзакциюФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("СоздатьТранзакциюПодтверждениеОперации", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		ОжидатьЗавершенияВыполненияВФоне(
			ОповещениеСледующее, 
			СервисКриптографииDSSСлужебныйВызовСервера.СоздатьТранзакцию(
					ВходящийКонтекст.НастройкиПользователя,
					ВходящийКонтекст.ДанныеЗапроса, 
					ВходящийКонтекст.КодОперации, 
					ВходящийКонтекст.ДанныеДокумента,
					ВходящийКонтекст.ПараметрыОперации),
			ВходящийКонтекст.ПараметрыОперации);
	Иначе
		СоздатьТранзакциюРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры СоздатьТранзакцию.
Процедура СоздатьТранзакциюПодтверждениеОперации(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ВходящийКонтекст.Вставить("ТрансформироватьРезультат", РезультатВыполнения.ТрансформироватьРезультат);
		ОбъектОповещения = Новый ОписаниеОповещения("СоздатьТранзакциюПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		
		ПараметрыПодтверждения = Новый Структура();
		ПараметрыПодтверждения.Вставить("ИдентификаторТранзакции", РезультатВыполнения.Результат);
		ПараметрыПодтверждения.Вставить("ЗаголовокФормы", ВходящийКонтекст.ОписаниеОперации);
		ПараметрыПодтверждения.Вставить("ТипПодтверждения", "Транзакция");
		
		ПодтвердитьОперацию(ВходящийКонтекст.НастройкиПользователя, ОповещениеСледующее, ПараметрыПодтверждения, ВходящийКонтекст.ПараметрыОперации);
		
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		СоздатьТранзакциюРезультат(РезультатВыполнения, ВходящийКонтекст);			
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("СоздатьТранзакциюФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		СоздатьТранзакциюРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли;
									
КонецПроцедуры	

// Продолжение процедуры СоздатьТранзакцию.
Процедура СоздатьТранзакциюПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		РезультатВыполнения.МаркерОбновлен = Истина;
		СоздатьТранзакциюРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		СоздатьТранзакциюРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("СоздатьТранзакциюФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		СоздатьТранзакциюРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры СоздатьТранзакцию.
Процедура СоздатьТранзакциюРезультат(РезультатВызова, ВходящийКонтекст)
	
	Если ВходящийКонтекст.Свойство("ТрансформироватьРезультат") Тогда
		РезультатВызова.Вставить("ТрансформироватьРезультат", ВходящийКонтекст.ТрансформироватьРезультат);
	КонецЕсли;
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область ПодтвердитьОперацию

// Вспомогательный цикл для запуска интерактивного процесса подтверждения
// Может вызывается из аутентификации, создании транзакции и произвольного подтверждения
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. запуск вложенного процесса интерактивного подтверждения (в отдельном модуле)
// 5. получение в случае успеха нового токена авторизации
// 6. сохранение нового токена для сеанса, возврат результата подтверждения.
//
Процедура ПодтвердитьОперацию(НастройкиПользователя, ОповещениеОЗавершении, ПараметрыПодтверждения, ПараметрыОперации = Неопределено)
	
	Заголовок = СвойствоСтруктуры(ПараметрыПодтверждения, "ЗаголовокФормы", 
					НСтр("ru = 'Подтверждение криптографической операции'", КодЯзыка()));
					
	// здесь
	ДанныеПодтверждения = СервисКриптографииDSSСлужебныйВызовСервера.ДанныеВторичнойАвторизацииПоУмолчанию(НастройкиПользователя);
	ДанныеПодтверждения.ИдентификаторТранзакции = СвойствоСтруктуры(ПараметрыПодтверждения, "ИдентификаторТранзакции", "");
	ДанныеПодтверждения.ИдентификаторОперации = СвойствоСтруктуры(ПараметрыПодтверждения, "ИдентификаторОперации", "");
	
	ДанныеПодтверждения.ТипПодтверждения = СвойствоСтруктуры(ПараметрыПодтверждения, "ТипПодтверждения", "Транзакция");
	ДанныеПодтверждения.ШаблонПодтверждения = СвойствоСтруктуры(ПараметрыПодтверждения, "ШаблонПодтверждения", "");
	ДанныеПодтверждения.Заголовок = Заголовок;
	
	МассивСпособов = СвойствоСтруктуры(ПараметрыОперации, "СпособПодтверждения");
	Если МассивСпособов = Неопределено Тогда	
		МассивСпособов = СервисКриптографииDSSСлужебныйВызовСервера.СписокВторичнойАвторизации();
	КонецЕсли;
	
	ВходящиеПараметры = ПроверитьПараметрыОперации(ПараметрыОперации);
	
	ДанныеПодтверждения.ДоступныеМетоды = МассивСпособов;
	ДанныеПодтверждения.ВторичнаяАвторизация = НастройкиПользователя.ВторичнаяАвторизация;
	ДанныеПодтверждения.Сертификат = СвойствоСтруктуры(ВходящиеПараметры, "Сертификат", Новый Структура);
	ДанныеПодтверждения.ДанныеДокументов = СвойствоСтруктуры(ВходящиеПараметры, "ДанныеДокументов");
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Подтверждение операции'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ДанныеПодтверждения", ДанныеПодтверждения);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ВходящиеПараметры);

	ОбъектОповещения = Новый ОписаниеОповещения("ПодтвердитьОперациюПослеВыполнения", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	СервисКриптографииDSSПодтверждениеКлиент.ОтправкаЗапроса(ОповещениеСледующее, НастройкиПользователя, ДанныеПодтверждения, ВходящиеПараметры);
	
КонецПроцедуры

// Продолжение процедуры ПодтвердитьОперацию.
Процедура ПодтвердитьОперациюПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	НастройкиПользователя	= ВходящийКонтекст.НастройкиПользователя;
	ДанныеПодтверждения		= ВходящийКонтекст.ДанныеПодтверждения;
	
	Если ДанныеПодтверждения.ТипПодтверждения = "Аутентификация"
		И СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ПодтвердитьОперациюРезультат(РезультатВыполнения, ВходящийКонтекст);
	Иначе	
		ОбъектОповещения 		= Новый ОписаниеОповещения("ПодтвердитьОперациюОтветПользователя", ЭтотОбъект);
		ОповещениеСледующее 	= ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		
		СервисКриптографииDSSПодтверждениеКлиент.ОбработатьРезультатЗапроса(
						ОповещениеСледующее,
						РезультатВыполнения, 
						НастройкиПользователя,
						ДанныеПодтверждения);
	КонецЕсли;
					
КонецПроцедуры

// Продолжение процедуры ПодтвердитьОперацию.
Процедура ПодтвердитьОперациюОтветПользователя(РезультатВызова, ВходящийКонтекст) Экспорт
	
	Если РезультатВызова = Неопределено Тогда
		РезультатВызова = ОтветСервисаПоУмолчанию(Ложь, "ОтказПользователя");
	КонецЕсли;

	Если РезультатВызова.Выполнено Тогда
		
		ДанныеПодтверждения = РезультатВызова.ДанныеПодтверждения;
		Если ДанныеПодтверждения.ЭтапЦикла = "Окончание" Тогда
			РезультатВызова.МаркерОбновлен = Истина;
			ПодтвердитьОперациюРезультат(РезультатВызова, ВходящийКонтекст);
		Иначе	
			ВходящийКонтекст.ДанныеПодтверждения = ДанныеПодтверждения;
			ОбъектОповещения = Новый ОписаниеОповещения("ПодтвердитьОперациюПослеВыполнения", ЭтотОбъект);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			СервисКриптографииDSSПодтверждениеКлиент.ОтправкаЗапроса(ОповещениеСледующее, 
					ВходящийКонтекст.НастройкиПользователя, 
					ДанныеПодтверждения,
					ВходящийКонтекст.ПараметрыОперации);
		КонецЕсли;	
			
	Иначе
		ПодтвердитьОперациюРезультат(РезультатВызова, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры ПодтвердитьОперацию.
Процедура ПодтвердитьОперациюРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область ПроверитьПинКодСертификата

// Вспомогательный процесс для проверки пин-кода сертификата
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. получение сведений о сертификате по отпечатку
// 4. проверка валидности пин-кода фоновым заданием
// 5. сохранение нового токена для сеанса, возврат результата проверки пин-кода.
//
Процедура ПроверитьПинКодСертификата(
			НастройкиПользователя,
			ОповещениеОЗавершении,
			ИдентификаторСертификата,
			ПинКодСертификата,
			ПараметрыОперации = Неопределено)
			
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Проверка пин-кода сертификата'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ИдентификаторСертификата", ИдентификаторСертификата);
	ПараметрыЦикла.Вставить("ПинКодСертификата", ПинКодСертификата);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ПроверитьПинКодСертификатаФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
	
КонецПроцедуры

// Продолжение процедуры ПроверитьПинКодСертификата.
Процедура ПроверитьПинКодСертификатаФоновымЗаданием(РезультатВызова, ВходящийКонтекст) Экспорт
	
	Если РезультатВызова.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПроверитьПинКодСертификатаПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		НоваяОперация = СервисКриптографииDSSСлужебныйВызовСервера.ВалидацияПинКодаСертификата(
					ВходящийКонтекст.НастройкиПользователя,
					ВходящийКонтекст.ИдентификаторСертификата, 
					ВходящийКонтекст.ПинКодСертификата, 
					ВходящийКонтекст.ПараметрыОперации);
					
		ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, НоваяОперация, ВходящийКонтекст.ПараметрыОперации);
					
	Иначе
		ПроверитьПинКодСертификатаРезультат(РезультатВызова, ВходящийКонтекст);
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры ПроверитьПинКодСертификата.
Процедура ПроверитьПинКодСертификатаПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	ПроверитьПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
	
КонецПроцедуры

// Продолжение процедуры ПроверитьПинКодСертификата.
Процедура ПроверитьПинКодСертификатаРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область ПинКодСертификата

// Вспомогательный процесс для ввода, проверки и смены пин-кода к закрытому ключу сертификата
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. получение сведений о сертификате по отпечатку
// 4. интерактивный ввод пин-кода (если его нет в сеансовых данных)
// 5. проверка валидности пин-кода фоновым заданием
// 6. проверка результата, если успешно то (7), иначе повторный ввод пин-код (4)
// 7. сохранение нового токена для сеанса, возврат результата проверки пин-кода.
//
Процедура ПинКодСертификата(
			НастройкиПользователя,
			ОповещениеОЗавершении,
			ИдентификаторСертификата,
			СменаПинКода = Ложь,
			ПараметрыОперации = Неопределено)
			
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Ввод пин-кода сертификата'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ИдентификаторСертификата", ИдентификаторСертификата);
	ПараметрыЦикла.Вставить("Сохранить", Ложь);
	ПараметрыЦикла.Вставить("ИзменилсяПинКод", Ложь);
	ПараметрыЦикла.Вставить("ОбновитьНастройки", Ложь);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ПинКодСертификатаПолучитьСертификат", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
	
КонецПроцедуры

// Продолжение процедуры ПинКодСертификата.
Процедура ПинКодСертификатаПолучитьСертификат(РезультатВызова, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(РезультатВызова, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		НашлиСертификат = СервисКриптографииDSSКлиентСервер.НайтиСертификат(ВходящийКонтекст.НастройкиПользователя,
												ВходящийКонтекст.ИдентификаторСертификата);
		
		Если НЕ ЗначениеЗаполнено(НашлиСертификат.Отпечаток) Тогда
			ОтветСервиса = ОтветСервисаПоУмолчанию(Ложь);
			ПолучитьОписаниеОшибки(ОтветСервиса, "СертификатыНеОбнаружены");
			ПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
		Иначе
			ВходящийКонтекст.Вставить("ОписаниеСертификата", НашлиСертификат);
			ПинКодСертификатаЗапросВвода(РезультатВызова, ВходящийКонтекст);
		КонецЕсли;
		
	Иначе
		ПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;
		
КонецПроцедуры

// Продолжение процедуры ПинКодСертификата.
// 
// Параметры:
//   РезультатВызова		- Структура
//  ВходящийКонтекст 	- Структура:
//    * ОписаниеСертификата - см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//
Процедура ПинКодСертификатаЗапросВвода(РезультатВызова, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(РезультатВызова, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		
		НастройкиПользователя 	= ВходящийКонтекст.НастройкиПользователя;
		ТекущийСертификат		= ВходящийКонтекст.ОписаниеСертификата;
		
		Если ТекущийСертификат.ТребуетсяПинКод Тогда
			Если ТребуетсяВводКонфиденциальныхДанных(ТекущийСертификат.ПинКод) Тогда
				ОбъектОповещения = Новый ОписаниеОповещения("ПинКодСертификатаПослеВвода", ЭтотОбъект);
				ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
				ОткрытьФормуВводПинКода(
						НастройкиПользователя,
						ОповещениеСледующее,
						ТекущийСертификат,
						ВходящийКонтекст.ПараметрыОперации);
				ВходящийКонтекст.ОбновитьНастройки = Истина;
			Иначе
				ОбъектОповещения = Новый ОписаниеОповещения("ПинКодСертификатаПослеПроверки", ЭтотОбъект);
				ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
				ПроверитьПинКодСертификата(НастройкиПользователя, 
											ОповещениеСледующее,
											ТекущийСертификат.Идентификатор,
											ТекущийСертификат.ПинКод,
											ВходящийКонтекст.ПараметрыОперации);
			КонецЕсли;
		Иначе
			ПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
		КонецЕсли;
		
	Иначе
		ПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПинКодСертификата.
// 
// Параметры:
//   РезультатВызова	- Структура
//  ВходящийКонтекст 	- Структура:
//    * ОписаниеСертификата - см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//
Процедура ПинКодСертификатаПослеВвода(РезультатВызова, ВходящийКонтекст) Экспорт
	
	Если РезультатВызова.Выполнено Тогда
		Если РезультатВызова.МаркерОбновлен Тогда
			НашлиСертификат = СервисКриптографииDSSКлиентСервер.НайтиСертификат(ВходящийКонтекст.НастройкиПользователя,
													ВходящийКонтекст.ИдентификаторСертификата);
			ВходящийКонтекст.Вставить("ОписаниеСертификата", НашлиСертификат);
		КонецЕсли;
		
		ТекущийСертификат		= ВходящийКонтекст.ОписаниеСертификата;
		ВходящийКонтекст.Вставить("Сохранить", СвойствоСтруктуры(РезультатВызова, "Сохранить", Ложь));
		ВходящийКонтекст.ОписаниеСертификата.ПинКод = РезультатВызова.Результат;
		
		Если ТекущийСертификат.ТребуетсяПинКод Тогда
			ОбъектОповещения = Новый ОписаниеОповещения("ПинКодСертификатаПослеПроверки", ЭтотОбъект);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			ПроверитьПинКодСертификата(ВходящийКонтекст.НастройкиПользователя, 
										ОповещениеСледующее,
										ТекущийСертификат.Идентификатор,
										ТекущийСертификат.ПинКод,
										ВходящийКонтекст.ПараметрыОперации);
		Иначе
			ПинКодСертификатаРезультат(РезультатВызова, ВходящийКонтекст);
		КонецЕсли;	
	Иначе
		ПинКодСертификатаРезультат(РезультатВызова, ВходящийКонтекст);
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры ПинКодСертификата.
Процедура ПинКодСертификатаПослеПроверки(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	ОписаниеСертификата = ВходящийКонтекст.ОписаниеСертификата;
	
	Если РезультатВыполнения.Выполнено Тогда
		ПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаПинКода(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПинКодСертификатаЗапросВвода", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ОписаниеСертификата.ПинКод = "";
		ОтобразитьОшибкуПользователю(ОповещениеСледующее, РезультатВыполнения.Ошибка, , ВходящийКонтекст.ПараметрыОперации);
		
	Иначе
		ОписаниеСертификата.ПинКод = "";
		УстановитьПинКодСертификата(ОписаниеСертификата, ВходящийКонтекст.НастройкиПользователя, ОписаниеСертификата.ПинКод, ВходящийКонтекст.Сохранить, , ВходящийКонтекст.ПараметрыОперации);
		РезультатВыполнения.Вставить("НастройкиПользователя", ВходящийКонтекст.НастройкиПользователя);
		ПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПинКодСертификата.
Процедура ПинКодСертификатаРезультат(РезультатВызова, ВходящийКонтекст)
	
	Если РезультатВызова.Выполнено Тогда
		ОписаниеСертификата = ВходящийКонтекст.ОписаниеСертификата;
		Результат = Новый Структура();
		Результат.Вставить("Сохранить", ВходящийКонтекст.Сохранить);
		Результат.Вставить("ПинКод", ОписаниеСертификата.ПинКод);
		Результат.Вставить("ОбновилиПинКод", ВходящийКонтекст.ОбновитьНастройки);
		
		Если ВходящийКонтекст.ОбновитьНастройки Тогда
			НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
			УстановитьПинКодСертификата(ОписаниеСертификата, НастройкиПользователя, ОписаниеСертификата.ПинКод, ВходящийКонтекст.Сохранить, , ВходящийКонтекст.ПараметрыОперации);
			Результат.Вставить("НастройкиПользователя", НастройкиПользователя);
		КонецЕсли;	
		
		РезультатВызова.Вставить("Результат", Результат);
	КонецЕсли;	
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область ПолучитьДанныеСертификата

// Запускает цикл получение основных сведений и содержимого сертификата
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. получение сведений о сертификате
// 4. проверка результата
// 5. сохранение нового токена для сеанса, возврат результата проверки пин-кода.
//
Процедура ПолучитьДанныеСертификата(НастройкиПользователя, 
			ОповещениеОЗавершении, 
			ИдентификаторСертификата,
			ПараметрыОперации) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Получение данных сертификата'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ИдентификаторСертификата", ИдентификаторСертификата);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ПолучитьДанныеСертификатаФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);

КонецПроцедуры	

// Продолжение процедуры ПолучитьДанныеСертификата.
Процедура ПолучитьДанныеСертификатаФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПолучитьДанныеСертификатаПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		ОжидатьЗавершенияВыполненияВФоне(
			ОповещениеСледующее, 
			СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьДанныеСертификата(
					ВходящийКонтекст.НастройкиПользователя,
					ВходящийКонтекст.ИдентификаторСертификата, 
					ВходящийКонтекст.ПараметрыОперации),
			ВходящийКонтекст.ПараметрыОперации);
	Иначе
		ПолучитьДанныеСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры ПолучитьДанныеСертификата.
Процедура ПолучитьДанныеСертификатаПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ПолучитьДанныеСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ПолучитьДанныеСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПолучитьДанныеСертификатаФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		ПолучитьДанныеСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПолучитьДанныеСертификата.
Процедура ПолучитьДанныеСертификатаРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область ПолучитьСвойстваСертификата

// Запускает цикл получение свойств сертификата сертификата
// Сервер возвращает данные в формате XML, c последующим преобразованием в структура с полями
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. получение свойств сертификата
// 4. сохранение нового токена для сеанса, возврат результата проверки пин-кода.
//
Процедура ПолучитьСвойстваСертификата(НастройкиПользователя, 
			ОповещениеОЗавершении, 
			ИдентификаторСертификата,
			ПараметрыОперации) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Получение сведений сертификата'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ИдентификаторСертификата", ИдентификаторСертификата);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ПолучитьСвойстваСертификатаФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);

КонецПроцедуры	

// Продолжение процедуры ПолучитьСвойстваСертификата.
Процедура ПолучитьСвойстваСертификатаФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПолучитьСвойстваСертификатаПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		ОжидатьЗавершенияВыполненияВФоне(
			ОповещениеСледующее, 
			СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьСвойстваСертификата(
					ВходящийКонтекст.НастройкиПользователя,
					ВходящийКонтекст.ИдентификаторСертификата, 
					ВходящийКонтекст.ПараметрыОперации),
			ВходящийКонтекст.ПараметрыОперации);
	Иначе
		ПолучитьСвойстваСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры ПолучитьСвойстваСертификата.
Процедура ПолучитьСвойстваСертификатаПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ПолучитьСвойстваСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ПолучитьСвойстваСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПолучитьСвойстваСертификатаФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		ПолучитьСвойстваСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПолучитьСвойстваСертификата.
Процедура ПолучитьСвойстваСертификатаРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область ОбновитьДанныеСертификатов

// Запускает цикл для процесса обновления кеша сертификатов
//
// Шаги цикла шифрования:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. запуск фонового задания для обновления кеша
// 4. проверка успешности окончания операции
// 5. сохранение нового токена для сеанса, возврат результата обновления кеша.
//
Процедура ОбновитьДанныеСертификатов(НастройкиПользователя, 
			ОповещениеОЗавершении, 
			ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Обновление кеша сертификатов'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ОбновитьДанныеСертификатовФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла, Ложь);

КонецПроцедуры	

// Продолжение процедуры ОбновитьДанныеСертификатов.
Процедура ОбновитьДанныеСертификатовФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ОбновитьДанныеСертификатовПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		ОжидатьЗавершенияВыполненияВФоне(
			ОповещениеСледующее, 
			СервисКриптографииDSSСлужебныйВызовСервера.ОбновитьДанныеСертификатов(
					ВходящийКонтекст.НастройкиПользователя,
					ВходящийКонтекст.ПараметрыОперации),
			ВходящийКонтекст.ПараметрыОперации);
	Иначе
		ОбновитьДанныеСертификатовРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры ОбновитьДанныеСертификатов.
Процедура ОбновитьДанныеСертификатовПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбновитьДанныеСертификатовРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ОбновитьДанныеСертификатовРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ОбновитьДанныеСертификатовФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		ОбновитьДанныеСертификатовРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ОбновитьДанныеСертификатов.
Процедура ОбновитьДанныеСертификатовРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область СоздатьЗапросНаСертификат

// Запускает цикл получения запроса на сертификат
// Данная процедура может быть запущена как интерактивно, 
// так и в "тихом" режиме, если переданы подготовленные данные для запроса
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. открытие формы для заполнения полей сертификата (по необходимости)
// 4. открытие формы запроса установки пин-кода (по необходимости)
// 5. запуск вложенного процесса подтверждения операции
// 6. проверка необходимости подтверждения, запуск вложенного процесса транзакции
// 7. создание нового запроса на сертификат 
// 8. обработка ошибки создания запроса
// 9. сохранение нового токена для сеанса, возврат содержимого запроса на сертификат.
//
Процедура СоздатьЗапросНаСертификат(НастройкиПользователя,
			ОповещениеОЗавершении, 
			ПараметрыОперации) Экспорт
	
	ГотовыйЗапрос 	= СвойствоСтруктуры(ПараметрыОперации, "ГотовыйЗапрос", Ложь);
	ПоляЗапроса		= СвойствоСтруктуры(ПараметрыОперации, "ПоляЗапроса", Новый Структура);
	ПодтверждатьПринудительно = СвойствоСтруктуры(ПараметрыОперации, "ПодтверждатьПринудительно", Ложь);
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Создание запроса на сертификат'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	ПараметрыЦикла.Вставить("ПоляЗапроса", ПоляЗапроса);
	ПараметрыЦикла.Вставить("ПодтверждатьПринудительно", ПодтверждатьПринудительно);
	
	РезультатВызова = ОтветСервисаПоУмолчанию();
	
	Если ГотовыйЗапрос Тогда
		РезультатВызова.Вставить("Результат", ПоляЗапроса);
		ОбъектОповещения = Новый ОписаниеОповещения("СоздатьЗапросНаСертификатВводПинКода", ЭтотОбъект);
	Иначе
		ОбъектОповещения = Новый ОписаниеОповещения("СоздатьЗапросНаСертификатЗаполнение", ЭтотОбъект);
	КонецЕсли;	
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
	
КонецПроцедуры

// Продолжение процедуры СоздатьЗапросНаСертификат.
Процедура СоздатьЗапросНаСертификатЗаполнение(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("СоздатьЗапросНаСертификатПослеЗаполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		
		ОткрытьФормуЗапросаНаСертификат(ВходящийКонтекст.НастройкиПользователя,
										ОповещениеСледующее,
										ВходящийКонтекст.ПоляЗапроса,
										ВходящийКонтекст.ПараметрыОперации);
									
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры СоздатьЗапросНаСертификат.
Процедура СоздатьЗапросНаСертификатПослеЗаполнения(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ВходящийКонтекст.ПоляЗапроса = РезультатВыполнения.Результат;
		СоздатьЗапросНаСертификатВводПинКода(РезультатВыполнения, ВходящийКонтекст);
	Иначе
		СоздатьЗапросНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры СоздатьЗапросНаСертификат.
Процедура СоздатьЗапросНаСертификатВводПинКода(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ПинКод = СвойствоСтруктуры(ВходящийКонтекст.ПоляЗапроса, "ПинКод");
		РежимПинКода = ВходящийКонтекст.НастройкиПользователя.Политика.РежимПинКода <> "Запрещено";
		
		Если ПинКод = Неопределено И РежимПинКода Тогда
			ОбъектОповещения = Новый ОписаниеОповещения("СоздатьЗапросНаСертификатПослеВводаПинКода", ЭтотОбъект);
			ОбработчикСледующий = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			ОткрытьФормуСменыПароля(ВходящийКонтекст.НастройкиПользователя, ОбработчикСледующий, "Установка", РежимПинКода = "Обязательно", ВходящийКонтекст.ПараметрыОперации);
		ИначеЕсли ПинКод = Неопределено Тогда
			ВходящийКонтекст.ПоляЗапроса.Вставить("ПинКод", "");
			СоздатьЗапросНаСертификатСоздатьТранзакцию(РезультатВыполнения, ВходящийКонтекст);
		Иначе
			СоздатьЗапросНаСертификатСоздатьТранзакцию(РезультатВыполнения, ВходящийКонтекст);
		КонецЕсли;	
				
	Иначе
		СоздатьЗапросНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры СоздатьЗапросНаСертификат.
Процедура СоздатьЗапросНаСертификатПослеВводаПинКода(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ВходящийКонтекст.ПоляЗапроса.Вставить("ПинКод", РезультатВыполнения.НовыйПинКод);
		СоздатьЗапросНаСертификатСоздатьТранзакцию(РезультатВыполнения, ВходящийКонтекст);
	Иначе
		СоздатьЗапросНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры	

// Продолжение процедуры СоздатьЗапросНаСертификат.
Процедура СоздатьЗапросНаСертификатСоздатьТранзакцию(ДлительнаяОперация, ВходящийКонтекст)
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		ПодтверждатьПринудительно = ВходящийКонтекст.ПодтверждатьПринудительно;
		КлючДействия = КлючДействияОперации("ЗапросНаСертификат", НастройкиПользователя);
		ВерсияПодтверждения = СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
		ВходящийКонтекст.Вставить("Транзакция", КлючДействия.Подтверждать);
		
		Если КлючДействия.Подтверждать ИЛИ ПодтверждатьПринудительно Тогда
			ПоляЗапроса 		= ВходящийКонтекст.ПоляЗапроса;
			
			Если ВерсияПодтверждения = 2 Тогда
				ОбъектОповещения 	= Новый ОписаниеОповещения("СоздатьЗапросНаСертификатПодтверждение", ЭтотОбъект);
				СледующееОповещение = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
				
				ПараметрыОперации	= ОбщегоНазначенияКлиент.СкопироватьРекурсивно(ВходящийКонтекст.ПараметрыОперации);
				ПараметрыОперации.Вставить("ПодтверждатьПринудительно", Истина);
				
				ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.СоздатьЗапросНаСертификат(
													НастройкиПользователя,
													ПоляЗапроса.УдостоверяющийЦентр,
													ПоляЗапроса.КриптоПровайдер,
													ПоляЗапроса.ШаблонСертификата,
													ПоляЗапроса.ПоляАтрибутов,
													ПоляЗапроса.ПинКод,
													ПараметрыОперации);
				ОжидатьЗавершенияВыполненияВФоне(СледующееОповещение, ОбработкаОперации, ВходящийКонтекст.ПараметрыОперации);
				
			Иначе
				ОбъектОповещения 	= Новый ОписаниеОповещения("СоздатьЗапросНаСертификатФоновымЗаданием", ЭтотОбъект);
				СледующееОповещение = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
				ПараметрыОперации	= СервисКриптографииDSSКлиентСервер.СвойстваТранзакцииЗапросНаСертификат(
												ПоляЗапроса.УдостоверяющийЦентр,
												ПоляЗапроса.ШаблонСертификата,
												ПоляЗапроса.ИмяСертификата);
							
				СоздатьТранзакцию(НастройкиПользователя,
						СледующееОповещение,
						ПараметрыОперации, 
						КлючДействия.КодОперации,
						НСтр("ru = 'Подтвердите создание запроса на сертификат.'", КодЯзыка()),
						, 
						ВходящийКонтекст.ПараметрыОперации);
			КонецЕсли;
					
		Иначе
			СоздатьЗапросНаСертификатФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст);
		КонецЕсли;
	Иначе
		СоздатьЗапросНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры СоздатьЗапросНаСертификат.
Процедура СоздатьЗапросНаСертификатПодтверждение(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("СоздатьЗапросНаСертификатФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		
		ПараметрыПодтверждения = Новый Структура();
		ПараметрыПодтверждения.Вставить("ИдентификаторОперации", РезультатВыполнения.Результат.ИдентификаторОперации);
		ПараметрыПодтверждения.Вставить("ЗаголовокФормы", НСтр("ru = 'Подтвердите создание запроса на сертификат'", КодЯзыка()));
		ПараметрыПодтверждения.Вставить("ТипПодтверждения", "Транзакция");
		
		ПодтвердитьОперацию(ВходящийКонтекст.НастройкиПользователя, ОповещениеСледующее, ПараметрыПодтверждения, ВходящийКонтекст.ПараметрыОперации);
		
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		СоздатьЗапросНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);			
	Иначе
		СоздатьЗапросНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры СоздатьЗапросНаСертификат.
Процедура СоздатьЗапросНаСертификатФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		
		ОбъектОповещения = Новый ОписаниеОповещения("СоздатьЗапросНаСертификатПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		ВходящийКонтекст.ПараметрыОперации.Вставить("Транзакция", ВходящийКонтекст.Транзакция);
		ПоляЗапроса = ВходящийКонтекст.ПоляЗапроса;
			
		ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.СоздатьЗапросНаСертификат(
											ВходящийКонтекст.НастройкиПользователя,
											ПоляЗапроса.УдостоверяющийЦентр,
											ПоляЗапроса.КриптоПровайдер,
											ПоляЗапроса.ШаблонСертификата,
											ПоляЗапроса.ПоляАтрибутов,
											ПоляЗапроса.ПинКод,
											ВходящийКонтекст.ПараметрыОперации);
											
		ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, ОбработкаОперации, ВходящийКонтекст.ПараметрыОперации);
		
	Иначе
		СоздатьЗапросНаСертификатОшибка(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры СоздатьЗапросНаСертификат.
Процедура СоздатьЗапросНаСертификатПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		СоздатьЗапросНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	Иначе
		СоздатьЗапросНаСертификатОшибка(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры СоздатьЗапросНаСертификат.
Процедура СоздатьЗапросНаСертификатОшибка(РезультатВыполнения, ВходящийКонтекст)
	
	Если НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		СоздатьЗапросНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("СоздатьЗапросНаСертификатФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаНеобработанныеЗапросы(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("СоздатьЗапросНаСертификатПослеПредупреждения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		СписокКоманд = Новый СписокЗначений;
		СписокКоманд.Добавить("Просмотреть", НСтр("ru = 'Открыть список'"), Истина);
		СписокКоманд.Добавить("Прервать", НСтр("ru = 'Прервать'"));
		ВывестиВопрос(ОповещениеСледующее, 
			НСтр("ru = 'Не удалось создать новый запрос на сертификат, т.к. на сервере обнаружены ранее созданные, но не обработанные запросы на сертификат. 
			|Просмотреть список ранее созданных запросов?'"),
			СписокКоманд,
			30,
			НСтр("ru = 'Обнаружены необработанные запросы'"),
			ВходящийКонтекст.ПараметрыОперации);
	Иначе
		СоздатьЗапросНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры СоздатьЗапросНаСертификат.
Процедура СоздатьЗапросНаСертификатПослеПредупреждения(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено И РезультатВыполнения.Результат = "Просмотреть" Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("СоздатьЗапросНаСертификатОбработка", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		УправлениеЗапросамиНаСертификат( 
					ВходящийКонтекст.НастройкиПользователя,
					ОповещениеСледующее,
					ВходящийКонтекст.ПараметрыОперации);
	ИначеЕсли РезультатВыполнения.Выполнено Тогда
		ОтветВызова = ОтветСервисаПоУмолчанию(Ложь, "ОтказПользователя");
		СоздатьЗапросНаСертификатРезультат(ОтветВызова, ВходящийКонтекст);
	Иначе				
		СоздатьЗапросНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры СоздатьЗапросНаСертификат.
Процедура СоздатьЗапросНаСертификатОбработка(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		Если ТипЗнч(РезультатВыполнения.Результат) = Тип("Число") Тогда
			ОбъектОповещения = Новый ОписаниеОповещения("СоздатьЗапросНаСертификатПроверитьПоля", ЭтотОбъект);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			СервисКриптографииDSSКлиент.ПолучитьЗапросНаСертификат(ОповещениеСледующее,
						ВходящийКонтекст.НастройкиПользователя,
						РезультатВыполнения.Результат,
						ВходящийКонтекст.ПараметрыОперации);
		ИначеЕсли РезультатВыполнения.Результат = Истина Тогда
			СоздатьЗапросНаСертификатФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст);
		КонецЕсли;	
	Иначе
		СоздатьЗапросНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры СоздатьЗапросНаСертификат.
Процедура СоздатьЗапросНаСертификатПроверитьПоля(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ПараметрыОперации = Новый Структура;
		ПараметрыОперации.Вставить("КлючевоеПоле", "OID");
		
		ПоляЗапроса = СервисКриптографииDSSASNКлиентСервер.ПолучитьСвойстваЗапросаНаСертификат(РезультатВыполнения.Результат.Содержание, ПараметрыОперации);
		ПоляНовые = ВходящийКонтекст.ПоляЗапроса.ПоляАтрибутов;
		ВсегоПравильных = ПоляНовые.Количество();
		
		Для Каждого СтрокаКлюча Из ПоляНовые Цикл
			Если СтрокаКлюча.Ключ = "2.5.4.3"
				ИЛИ ВРег(СтрокаКлюча.Значение) = ВРег(ПоляЗапроса.Владелец[СтрокаКлюча.Ключ]) Тогда
				ВсегоПравильных = ВсегоПравильных - 1;
			КонецЕсли;	
		КонецЦикла;
		
		Если ВсегоПравильных > 0 Тогда
			РезультатВыполнения = ОтветСервисаПоУмолчанию(Ложь, "ПоляВыбранногоЗапросаНаСертификат")
		КонецЕсли;
		
	КонецЕсли;	
		
	Если НЕ РезультатВыполнения.Выполнено Тогда
		СоздатьЗапросНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);			
	Иначе
		СоздатьЗапросНаСертификатПослеВыполнения(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры СоздатьЗапросНаСертификат.
Процедура СоздатьЗапросНаСертификатРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область УправлениеЗапросамиНаСертификат

// Запускает цикл управления (просмотр, удаление, получение) для запросов на сертификат
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. получение списка запросов в статусе: обрабатывается
// 4. открытие формы со списком запросов
// 5. обработка результата выбора в форме выбора: удаление, выбор
// 6. сохранение нового токена для сеанса, возврат содержимого результата.
//
Процедура УправлениеЗапросамиНаСертификат(НастройкиПользователя, 
			ОповещениеОЗавершении,
			ПараметрыОперации)
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Выбор запроса на сертификат'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("УправлениеЗапросамиНаСертификатСписокЗапросов", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
	
КонецПроцедуры

// Продолжение процедуры УправлениеЗапросамиНаСертификат.
Процедура УправлениеЗапросамиНаСертификатСписокЗапросов(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("УправлениеЗапросамиНаСертификатПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		СервисКриптографииDSSКлиент.СписокЗапросовНаСертификат(ОповещениеСледующее,
			ВходящийКонтекст.НастройкиПользователя,
			ВходящийКонтекст.ПараметрыОперации);
			
	Иначе
		УправлениеЗапросамиНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры УправлениеЗапросамиНаСертификат.
Процедура УправлениеЗапросамиНаСертификатПослеВыполнения(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("УправлениеЗапросамиНаСертификатРезультат", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ОткрытьФормуВыбораСертификата(ВходящийКонтекст.НастройкиПользователя, 
									ОповещениеСледующее,
									"Запросы",
									Ложь,
									РезультатВыполнения.Результат,
									ВходящийКонтекст.ПараметрыОперации);
		
	Иначе
		УправлениеЗапросамиНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
		
		
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры УправлениеЗапросамиНаСертификат.
Процедура УправлениеЗапросамиНаСертификатРезультат(РезультатВызова, ВходящийКонтекст) Экспорт
	
	ПодготовленныйРезультат = ПодготовитьПсевдонимыОтвета(РезультатВызова, ВходящийКонтекст.ПараметрыОперации);
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова, ПодготовленныйРезультат);
	
КонецПроцедуры

#КонецОбласти

#Область ОбработатьЗапросыНаСертификат

// Запускает цикл обработки функций для запросов на сертификат
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. выполнение функции на сервере
// 4. сохранение нового токена для сеанса, возврат содержимого результата.
//
Процедура ОбработатьЗапросыНаСертификат(НастройкиПользователя,
			ОповещениеОЗавершении,
			ВыполняемоеДействие,
			ПараметрыВызова = Неопределено,
			ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Обработка запроса на сертификат'", КодЯзыка()) + ": " + ВыполняемоеДействие);
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ВыполняемоеДействие", ВыполняемоеДействие);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	ПараметрыЦикла.Вставить("ИдентификаторЗапроса", СвойствоСтруктуры(ПараметрыВызова, "ИдентификаторЗапроса", 0));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ОбработатьЗапросыНаСертификатФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
	
КонецПроцедуры

// Продолжение процедуры ОбработатьЗапросыНаСертификат.
Процедура ОбработатьЗапросыНаСертификатФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ОбработатьЗапросыНаСертификатПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
		
		ВыполняемоеДействие = ВходящийКонтекст.ВыполняемоеДействие;
		
		Если ВыполняемоеДействие = "СписокЗапросовНаСертификат" Тогда
			ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.СписокЗапросовНаСертификат(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ПараметрыОперации);
		ИначеЕсли ВыполняемоеДействие = "ПолучитьЗапросНаСертификат" Тогда
			ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьЗапросНаСертификат(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ИдентификаторЗапроса, 
						ВходящийКонтекст.ПараметрыОперации);
		ИначеЕсли ВыполняемоеДействие = "УдалитьЗапросНаСертификат" Тогда
			ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.УдалитьЗапросНаСертификат(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ИдентификаторЗапроса, 
						ВходящийКонтекст.ПараметрыОперации);
		КонецЕсли;
		
		ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, ДействияНаСервере, ВходящийКонтекст.ПараметрыОперации);
		
	Иначе
		ОбработатьЗапросыНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры ОбработатьЗапросыНаСертификат.
Процедура ОбработатьЗапросыНаСертификатПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбработатьЗапросыНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ОбработатьЗапросыНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ОбработатьДокументФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		ОбработатьЗапросыНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ОбработатьЗапросыНаСертификат.
Процедура ОбработатьЗапросыНаСертификатРезультат(РезультатВызова, ВходящийКонтекст)
	
	ПодготовленныйРезультат = ПодготовитьПсевдонимыОтвета(РезультатВызова, ВходящийКонтекст.ПараметрыОперации);
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова, ПодготовленныйРезультат);
	
КонецПроцедуры

#КонецОбласти

#Область ПолучитьИнформациюУдостоверяющихЦентров

// Запускает цикл получения данных об удостоверяющих центрах доступных пользователю
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. получение списка УЦ из сеансовых настроек пользователя
// 4. сохранение нового токена для сеанса, возврат списка УЦ.
//
Процедура ПолучитьИнформациюУдостоверяющихЦентров(НастройкиПользователя,
			ОповещениеОЗавершении, 
			ПараметрыОперации) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Получение информации об УЦ'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ПолучитьИнформациюУдостоверяющихЦентровЗаполнение", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
	
КонецПроцедуры

// Продолжение процедуры ПолучитьИнформациюУдостоверяющихЦентров.
Процедура ПолучитьИнформациюУдостоверяющихЦентровЗаполнение(РезультатВызова, ВходящийКонтекст) Экспорт
	
	Если РезультатВызова.Выполнено Тогда
		
		Результат = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьИнформациюУдостоверяющихЦентров(
				ВходящийКонтекст.НастройкиПользователя, 
				ВходящийКонтекст.ПараметрыОперации);
				
		РезультатВызова.Вставить("Результат", Результат);
		
	КонецЕсли;	
	
	ПолучитьИнформациюУдостоверяющихЦентровРезультат(РезультатВызова, ВходящийКонтекст);
	
КонецПроцедуры

// Продолжение процедуры ПолучитьИнформациюУдостоверяющихЦентров.
Процедура ПолучитьИнформациюУдостоверяющихЦентровРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область УстановитьСертификат

// Запускает цикл установки сертификата на сервере облачной криптографии
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. установка переданного сертификата фоновым заданием
// 4. сохранение нового токена для сеанса, возврат результата успеха.
//
Процедура УстановитьСертификат(НастройкиПользователя, 
			ОповещениеОЗавершении, 
			ДанныеСертификата,
			ПараметрыОперации) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Установка сертификата'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ДанныеСертификата", ДанныеСертификата);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("УстановитьСертификатФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);

КонецПроцедуры	

// Продолжение процедуры УстановитьСертификат.
Процедура УстановитьСертификатФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("УстановитьСертификатПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		ОжидатьЗавершенияВыполненияВФоне(
			ОповещениеСледующее, 
			СервисКриптографииDSSСлужебныйВызовСервера.УстановитьСертификат(
					ВходящийКонтекст.НастройкиПользователя,
					ВходящийКонтекст.ДанныеСертификата, 
					ВходящийКонтекст.ПараметрыОперации),
			ВходящийКонтекст.ПараметрыОперации);
	Иначе
		УстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры УстановитьСертификат.
Процедура УстановитьСертификатПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		УстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		УстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("УстановитьСертификатФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		УстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры УстановитьСертификат.
Процедура УстановитьСертификатРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область НайтиСертификат

// Запускает цикл поиска сертификат
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. получение данных сертификата
// 4. создание объекта сертификата платформы 
// 5. сохранение нового токена для сеанса, возврат результата успеха.
//
Процедура НайтиСертификат(ОповещениеОЗавершении, ОписаниеСертификата, ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("ОписаниеСертификата", ОписаниеСертификата);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	Если ИспользованиеОблачнойПодписиВозможно(ПараметрыЦикла) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("НайтиСертификатФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
		ВыполнитьОбработкуОповещения(ОповещениеСледующее, Неопределено);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры НайтиСертификат.
Процедура НайтиСертификатФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	ОбъектОповещения = Новый ОписаниеОповещения("НайтиСертификатПослеВыполнения", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	НачатьЗамерВремени(ВходящийКонтекст);
		
	ОжидатьЗавершенияВыполненияВФоне(
		ОповещениеСледующее, 
		СервисКриптографииDSSСлужебныйВызовСервера.НайтиСертификат(
				ВходящийКонтекст.ОписаниеСертификата, 
				ВходящийКонтекст.ПараметрыОперации),
		ВходящийКонтекст.ПараметрыОперации);
	
КонецПроцедуры
			
// Продолжение процедуры НайтиСертификат.
Процедура НайтиСертификатПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	НайтиСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	
КонецПроцедуры

// Продолжение процедуры НайтиСертификат.
Процедура НайтиСертификатРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область НазначитьОсновнымСертификат

// Запускает цикл назначение сертификата основным (по умолчанию) на стороне сервера облачной криптографии
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. проверка и поиск идентификатор сертификата
// 4. установка / снятие переданного ид сертификата основным в фоновом задании
// 5. сохранение нового токена для сеанса, возврат результат успеха.
//
Процедура НазначитьОсновнымСертификат(НастройкиПользователя, 
			ОповещениеОЗавершении, 
			Сертификат,
			Установить,
			ПараметрыОперации) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Установка основного сертификата'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("Сертификат", Сертификат);
	ПараметрыЦикла.Вставить("Установить", Установить);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("НазначитьОсновнымСертификатПолучитьСертификат", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);

КонецПроцедуры	

// Продолжение процедуры НазначитьОсновнымСертификат.
Процедура НазначитьОсновнымСертификатПолучитьСертификат(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		ПроверитьТокенНаОбновление(РезультатВыполнения, НастройкиПользователя);
		
		ТекущийСертификат = СервисКриптографииDSSКлиентСервер.НайтиСертификат(ВходящийКонтекст.НастройкиПользователя, ВходящийКонтекст.Сертификат);
		
		Если НЕ ЗначениеЗаполнено(ТекущийСертификат.Отпечаток) Тогда
			ОтветСервиса = ОтветСервисаПоУмолчанию(Ложь);
			ПолучитьОписаниеОшибки(ОтветСервиса, "СертификатыНеОбнаружены");
			СменитьПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
		Иначе
			ВходящийКонтекст.Вставить("ОписаниеСертификата", ТекущийСертификат);
			ОбъектОповещения = Новый ОписаниеОповещения("НазначитьОсновнымСертификатРезультат", ЭтотОбъект);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			НазначитьОсновнымСертификатФоновымЗаданием(ОтветСервисаПоУмолчанию(Истина), ВходящийКонтекст);
		КонецЕсли;
		
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		НазначитьОсновнымСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("НазначитьОсновнымСертификатРезультат", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
		
	Иначе
		НазначитьОсновнымСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры НазначитьОсновнымСертификат.
// 
// Параметры:
//   РезультатВыполнения	- Структура
//  ВходящийКонтекст 	- Структура:
//    * ОписаниеСертификата - см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//
Процедура НазначитьОсновнымСертификатФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("НазначитьОсновнымСертификатПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		ОжидатьЗавершенияВыполненияВФоне(
			ОповещениеСледующее, 
			СервисКриптографииDSSСлужебныйВызовСервера.НазначитьОсновнымСертификат(
					ВходящийКонтекст.НастройкиПользователя,
					ВходящийКонтекст.ОписаниеСертификата.Идентификатор,
					ВходящийКонтекст.Установить,
					ВходящийКонтекст.ПараметрыОперации),
		ВходящийКонтекст.ПараметрыОперации);
	Иначе
		НазначитьОсновнымСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры НазначитьОсновнымСертификат.
Процедура НазначитьОсновнымСертификатПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		НазначитьОсновнымСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		НазначитьОсновнымСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("НазначитьОсновнымСертификатФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		НазначитьОсновнымСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры НазначитьОсновнымСертификат.
Процедура НазначитьОсновнымСертификатРезультат(РезультатВызова, ВходящийКонтекст) Экспорт
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область СменитьПинКодСертификата

// Запускает цикл смены пин-кода для указанного сертификата
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. получение данных сертификата
// 4. запуск вложенного процесса ввода старого и нового пин-кода, проверка текущего пин-кода
// 5. запуск вложенного процесса подтверждения операции, при необходимости
// 6. запуск фонового задания для смены пин-код
// 7. проверка результата смены пин-кода
// 8. сохранение нового токена для сеанса, возврат результат успеха.
//
Процедура СменитьПинКодСертификата(НастройкиПользователя, 
			ОповещениеОЗавершении, 
			Сертификат,
			ПараметрыОперации = Неопределено) Экспорт
			
	Если НастройкиПользователя = Неопределено Тогда
		ТекущиеНастройки = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьНастройкиПользователяПоСертификату(Сертификат, ПараметрыОперации);
	Иначе
		ТекущиеНастройки = НастройкиПользователя;
	КонецЕсли;
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Смена пин-кода сертификата'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", ТекущиеНастройки);
	ПараметрыЦикла.Вставить("Сертификат", Сертификат);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("СменитьПинКодСертификатаПолучитьСертификат", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
			
КонецПроцедуры	

// Продолжение процедуры СменитьПинКодСертификата.
Процедура СменитьПинКодСертификатаПолучитьСертификат(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		ПроверитьТокенНаОбновление(РезультатВыполнения, НастройкиПользователя);
		
		ТекущийСертификат = СервисКриптографииDSSКлиентСервер.НайтиСертификат(ВходящийКонтекст.НастройкиПользователя, ВходящийКонтекст.Сертификат);
		
		Если НЕ ЗначениеЗаполнено(ТекущийСертификат.Отпечаток) Тогда
			ОтветСервиса = ОтветСервисаПоУмолчанию(Ложь);
			ПолучитьОписаниеОшибки(ОтветСервиса, "СертификатыНеОбнаружены");
			СменитьПинКодСертификатаРезультат(ОтветСервиса, ВходящийКонтекст);
		ИначеЕсли НастройкиПользователя.Политика.РежимПинКода = "Запрещено" Тогда
			ОтветСервиса = ОтветСервисаПоУмолчанию(Ложь);
			ПолучитьОписаниеОшибки(ОтветСервиса, "ОшибкаВыполнения", НСтр("ru = 'Настройки сервера DSS запрещают использование пин-кодов.'"));
			СменитьПинКодСертификатаРезультат(ОтветСервиса, ВходящийКонтекст);
		Иначе
			ВходящийКонтекст.Вставить("ОписаниеСертификата", ТекущийСертификат);
			ОбъектОповещения = Новый ОписаниеОповещения("СменитьПинКодСертификатаПослеВвода", ЭтотОбъект);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			ОткрытьФормуСменыПароля(ВходящийКонтекст.НастройкиПользователя,
			ОповещениеСледующее, 
				?(ТекущийСертификат.ТребуетсяПинКод, "Смена", "Установка"),
				Ложь,
				ВходящийКонтекст.ПараметрыОперации);
		КонецЕсли;
		
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		СменитьПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("СменитьПинКодСертификатаРезультат", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
		
	Иначе
		СменитьПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры СменитьПинКодСертификата.
// 
// Параметры:
//   РезультатВызова		- Структура
//  ВходящийКонтекст	- Структура:
//    * ОписаниеСертификата - см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//
Процедура СменитьПинКодСертификатаПослеВвода(РезультатВызова, ВходящийКонтекст) Экспорт
	
	Если РезультатВызова.Выполнено Тогда
		ТекущийСертификат		= ВходящийКонтекст.ОписаниеСертификата;
		ВходящийКонтекст.Вставить("Сохранить", РезультатВызова.Сохранить);
		ВходящийКонтекст.Вставить("СтарыйПинКод", РезультатВызова.Результат);
		ВходящийКонтекст.Вставить("НовыйПинКод", РезультатВызова.НовыйПинКод);
		
		Если ТекущийСертификат.ТребуетсяПинКод Тогда
			ОбъектОповещения = Новый ОписаниеОповещения("СменитьПинКодСертификатаПроверкаПинКода", ЭтотОбъект);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			ПроверитьПинКодСертификата(ВходящийКонтекст.НастройкиПользователя, 
										ОповещениеСледующее,
										ВходящийКонтекст.ОписаниеСертификата.Идентификатор,
										ВходящийКонтекст.СтарыйПинКод,
										ВходящийКонтекст.ПараметрыОперации)
		Иначе
			СменитьПинКодСертификатаПроверкаПинКода(РезультатВызова, ВходящийКонтекст);
		КонецЕсли;	
	Иначе
		СменитьПинКодСертификатаРезультат(РезультатВызова, ВходящийКонтекст);
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры СменитьПинКодСертификата.
Процедура СменитьПинКодСертификатаПроверкаПинКода(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		СменитьПинКодСертификатаСоздатьТранзакцию(РезультатВыполнения, ВходящийКонтекст);
		
	Иначе
		СменитьПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры СменитьПинКодСертификата.
// 
// Параметры:
//   РезультатВыполнения	- Структура
//  ВходящийКонтекст 	- Структура:
//    * ОписаниеСертификата - см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//
Процедура СменитьПинКодСертификатаСоздатьТранзакцию(ДлительнаяОперация, ВходящийКонтекст)
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		ВерсияПодтверждения = СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);
		КлючДействия = КлючДействияОперации("СменаПинКода", НастройкиПользователя);
		ВходящийКонтекст.Вставить("Транзакция", КлючДействия.Подтверждать);
		
		Если КлючДействия.Подтверждать Тогда
			ОписаниеСертификата = ВходящийКонтекст.ОписаниеСертификата;
			
			Если ВерсияПодтверждения = 2 Тогда
				ОбъектОповещения 	= Новый ОписаниеОповещения("СменитьПинКодСертификатаПодтверждение", ЭтотОбъект);
				СледующееОповещение = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
				ПараметрыОперации	= ОбщегоНазначенияКлиент.СкопироватьРекурсивно(ВходящийКонтекст.ПараметрыОперации);
				ПараметрыОперации.Вставить("ПодтверждатьПринудительно", Истина);
				
				ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.СменитьПинКодСертификата(
						ВходящийКонтекст.НастройкиПользователя,
						ОписаниеСертификата.Идентификатор,
						ВходящийКонтекст.СтарыйПинКод,
						ВходящийКонтекст.НовыйПинКод,
						ПараметрыОперации);
				ОжидатьЗавершенияВыполненияВФоне(СледующееОповещение, ОбработкаОперации, ВходящийКонтекст.ПараметрыОперации);
				
			Иначе
				ОбъектОповещения 	= Новый ОписаниеОповещения("СменитьПинКодСертификатаФоновымЗаданием", ЭтотОбъект);
				СледующееОповещение = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
				ПараметрыТранзакции	= СервисКриптографииDSSКлиентСервер.СвойстваТранзакцииСменыПинКода(ОписаниеСертификата.Идентификатор);
				СоздатьТранзакцию(НастройкиПользователя,
						СледующееОповещение,
						ПараметрыТранзакции, 
						КлючДействия.КодОперации,
						НСтр("ru = 'Подтвердите смену пин-кода.'", КодЯзыка()),
						,
						ВходящийКонтекст.ПараметрыОперации);
				
			КонецЕсли;
					
		Иначе
			СменитьПинКодСертификатаФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст);
		КонецЕсли;
	Иначе
		СменитьПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры СменитьПинКодСертификата.
Процедура СменитьПинКодСертификатаПодтверждение(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("СменитьПинКодСертификатаФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		
		ПараметрыПодтверждения = Новый Структура();
		ПараметрыПодтверждения.Вставить("ИдентификаторОперации", РезультатВыполнения.Результат.ИдентификаторОперации);
		ПараметрыПодтверждения.Вставить("ЗаголовокФормы", НСтр("ru = 'Подтвердите смену пин-код'", КодЯзыка()));
		ПараметрыПодтверждения.Вставить("ТипПодтверждения", "Транзакция");
		
		ПодтвердитьОперацию(ВходящийКонтекст.НастройкиПользователя, ОповещениеСледующее, ПараметрыПодтверждения, ВходящийКонтекст.ПараметрыОперации);
		
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		СменитьПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);			
	Иначе
		СменитьПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры СменитьПинКодСертификата.
// 
// Параметры:
//   РезультатВыполнения	- Структура
//  ВходящийКонтекст 	- Структура:
//    * ОписаниеСертификата - см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//
Процедура СменитьПинКодСертификатаФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("СменитьПинКодСертификатаПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		ОписаниеСертификата = ВходящийКонтекст.ОписаниеСертификата;
		ВходящийКонтекст.ПараметрыОперации.Вставить("Транзакция", ВходящийКонтекст.Транзакция);
		Если ОписаниеСертификата.ТребуетсяПинКод Тогда
			ВходящийКонтекст.НастройкиПользователя = РезультатВыполнения.НастройкиПользователя;
		КонецЕсли;	
		
		НоваяОперация = СервисКриптографииDSSСлужебныйВызовСервера.СменитьПинКодСертификата(
						ВходящийКонтекст.НастройкиПользователя,
						ОписаниеСертификата.Идентификатор,
						ВходящийКонтекст.СтарыйПинКод,
						ВходящийКонтекст.НовыйПинКод,
						ВходящийКонтекст.ПараметрыОперации);
					
		ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, НоваяОперация, ВходящийКонтекст.ПараметрыОперации);
					
	Иначе
		СменитьПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры СменитьПинКодСертификата.
Процедура СменитьПинКодСертификатаПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		РезультатВыполнения.Вставить("Результат", ВходящийКонтекст.НовыйПинКод);
		ОписаниеСертификата = ВходящийКонтекст.ОписаниеСертификата;
		НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
		
		ОписаниеСертификата.ПинКод = ВходящийКонтекст.НовыйПинКод;
		УстановитьПинКодСертификата(ОписаниеСертификата, НастройкиПользователя, ОписаниеСертификата.ПинКод, ВходящийКонтекст.Сохранить, Истина, ВходящийКонтекст.ПараметрыОперации);
	КонецЕсли;
	
	СменитьПинКодСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);
	
КонецПроцедуры

// Продолжение процедуры СменитьПинКодСертификата.
Процедура СменитьПинКодСертификатаРезультат(РезультатВызова, ВходящийКонтекст) Экспорт
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область ПроверитьСертификат

// Запускает цикл проверки валидности сертификата
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка настроек пользователей
// 3. запуск фонового задания для проверки сертификата в цикле
// 4. проверка результата выполнения
// 5. возврат результат успеха.
//
Процедура ПроверитьСертификат(НастройкиПользователя, ОповещениеОЗавершении, ДанныеСертификата, ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Проверка сертификата'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ДанныеСертификата", ДанныеСертификата);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	СервисКриптографииDSSКлиентСервер.ПолучитьОписаниеОшибки(ПараметрыЦикла, "ОтсутствиеНастроек");
	
	НашлиНастройки = Новый Массив;
	Если НастройкиПользователя = Неопределено Тогда 
		Отбор = Новый Соответствие;
		Отбор.Вставить("Методы.СервисПроверки", "Заполнено");
		НашлиНастройки = СервисКриптографииDSSСлужебныйВызовСервера.ПодобратьНастройкиПользователя(Отбор, ПараметрыЦикла.ПараметрыОперации);
	Иначе
		НашлиНастройки.Добавить(НастройкиПользователя);
	КонецЕсли;
	
	ПараметрыЦикла.Вставить("НастройкиПодключения", НашлиНастройки);
	ПараметрыЦикла.Вставить("Индекс", 0);
	
	// сервис проверки не требует аутентификации
	ПроверитьСертификатПоОчереди(ПараметрыЦикла);
	
КонецПроцедуры	

// Продолжение процедуры ПроверитьПодпись.
Процедура ПроверитьСертификатПоОчереди(ВходящийКонтекст)
	
	ТекущийИндекс = ВходящийКонтекст.Индекс;
	НастройкиПодключения = ВходящийКонтекст.НастройкиПодключения;
	ПараметрыОперации = ВходящийКонтекст.ПараметрыОперации;
	
	Если ВходящийКонтекст.НастройкиПодключения.Количество() > ТекущийИндекс Тогда
		ВходящийКонтекст.Индекс = ВходящийКонтекст.Индекс + 1;
		ВходящийКонтекст.НастройкиПользователя = СервисКриптографииDSSКлиент.ПолучитьНастройкиПользователя(НастройкиПодключения[ТекущийИндекс], ПараметрыОперации);
		ПроверитьСертификатФоновымЗаданием(ВходящийКонтекст);
	Иначе
		РезультатВыполнения = ОтветСервисаПоУмолчанию(Ложь);
		РезультатВыполнения.КодОшибки = ВходящийКонтекст.КодОшибки;
		РезультатВыполнения.Ошибка = ВходящийКонтекст.Ошибка;
		РезультатВыполнения.СтатусОшибки = ВходящийКонтекст.СтатусОшибки;
		РезультатВыполнения.Вставить("НастройкиПользователя", ВходящийКонтекст.НастройкиПользователя);
		ПроверитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПроверитьСертификат.
Процедура ПроверитьСертификатФоновымЗаданием(ВходящийКонтекст)
	
	ОбъектОповещения = Новый ОписаниеОповещения("ПроверитьСертификатПослеВыполнения", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	НачатьЗамерВремени(ВходящийКонтекст);
		
	ОжидатьЗавершенияВыполненияВФоне(
		ОповещениеСледующее, 
		СервисКриптографииDSSСлужебныйВызовСервера.ПроверитьСертификат(
				ВходящийКонтекст.НастройкиПользователя,
				ВходящийКонтекст.ДанныеСертификата,
				ВходящийКонтекст.ПараметрыОперации),
		ВходящийКонтекст.ПараметрыОперации);
	
КонецПроцедуры

// Продолжение процедуры ПроверитьСертификат.
Процедура ПроверитьСертификатПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ПроверитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	Иначе
		ВходящийКонтекст.КодОшибки = РезультатВыполнения.КодОшибки;
		ВходящийКонтекст.Ошибка = РезультатВыполнения.Ошибка;
		ВходящийКонтекст.СтатусОшибки = РезультатВыполнения.СтатусОшибки;
		ПроверитьСертификатПоОчереди(ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПроверитьСертификат.
Процедура ПроверитьСертификатРезультат(РезультатВызова, ВходящийКонтекст)
	
	ПодготовленныйРезультат = ПодготовитьПсевдонимыОтвета(РезультатВызова, ВходящийКонтекст.ПараметрыОперации);
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова, ПодготовленныйРезультат);
	
КонецПроцедуры

#КонецОбласти

#Область ПолучитьСведенияОПодписантах

// Запускает цикл получения сведений о подписантах данных
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя, вложенный процесс
// 3. запуск фонового задания для получения списка подписантов
// 4. проверка результата выполнения
// 5. возврат результат успеха.
//
Процедура ПолучитьСведенияОПодписантах(НастройкиПользователя, ОповещениеОЗавершении, ДанныеДокумента, ТипПодписи, ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Получение сведений о подписантах'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ДанныеДокумента", ДанныеДокумента);
	ПараметрыЦикла.Вставить("ТипПодписи", ТипПодписи);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ПолучитьСведенияОПодписантахФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	
	Отбор = Новый Соответствие;
	Отбор.Вставить("Методы.ПроверкаСертификата", "Заполнено");
	ПроверкаАутентификацииПользователяСОтбором(ОповещениеСледующее, ПараметрыЦикла, Отбор);

КонецПроцедуры	

// Продолжение процедуры ПолучитьСведенияОПодписантах.
Процедура ПолучитьСведенияОПодписантахФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПолучитьСведенияОПодписантахПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		ОжидатьЗавершенияВыполненияВФоне(
			ОповещениеСледующее, 
			СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьСведенияОПодписантах(
					ВходящийКонтекст.НастройкиПользователя,
					ВходящийКонтекст.ДанныеДокумента,
					ВходящийКонтекст.ТипПодписи,
					ВходящийКонтекст.ПараметрыОперации),
		ВходящийКонтекст.ПараметрыОперации);
	Иначе
		ПолучитьСведенияОПодписантахРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры ПолучитьСведенияОПодписантах.
Процедура ПолучитьСведенияОПодписантахПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ПолучитьСведенияОПодписантахРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ПолучитьСведенияОПодписантахРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПолучитьСведенияОПодписантахФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		ПолучитьСведенияОПодписантахРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПолучитьСведенияОПодписантах.
Процедура ПолучитьСведенияОПодписантахРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область ПроверитьПодпись

// Запускает цикл проверки валидности подписи данных
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка настроек подключения пользователей
// 3. запуск фонового задания для проверки подписи в цикле
// 4. проверка результата выполнения
// 5. возврат результат успеха.
//
Процедура ПроверитьПодпись(НастройкиПользователя, 
					ОповещениеОЗавершении,
					ДанныеДокумента,
					ИсходныйДокумент,
					ТипПодписи,
					ПараметрыОперации = Неопределено) Экспорт
					
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Проверка подписи'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ДанныеДокумента", ДанныеДокумента);
	ПараметрыЦикла.Вставить("ТипПодписи", ТипПодписи);
	ПараметрыЦикла.Вставить("ИсходныйДокумент", ИсходныйДокумент);
	ПараметрыЦикла.Вставить("СвойстваПроверки", СвойствоСтруктуры(ПараметрыОперации, "СвойстваПроверки"));
	ПараметрыЦикла.Вставить("Сертификат", СвойствоСтруктуры(ПараметрыОперации, "Сертификат"));
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	ПараметрыЦикла.Вставить("Индекс", 0);
	
	СервисКриптографииDSSКлиентСервер.ПолучитьОписаниеОшибки(ПараметрыЦикла, "ОтсутствиеНастроек");
	
	НашлиНастройки = Новый Массив;
	Если НастройкиПользователя = Неопределено Тогда 
		Отбор = Новый Соответствие;
		Отбор.Вставить("Методы.СервисПроверки", "Заполнено");
		НашлиНастройки = СервисКриптографииDSSСлужебныйВызовСервера.ПодобратьНастройкиПользователя(Отбор, ПараметрыЦикла.ПараметрыОперации);
	Иначе
		НашлиНастройки.Добавить(НастройкиПользователя);
	КонецЕсли;
	
	ПараметрыЦикла.Вставить("НастройкиПодключения", НашлиНастройки);
	
	// сервис проверки не требует аутентификации
	ПроверитьПодписьПоОчереди(ПараметрыЦикла);
	
КонецПроцедуры					

// Продолжение процедуры ПроверитьПодпись.
Процедура ПроверитьПодписьПоОчереди(ВходящийКонтекст)
	
	ТекущийИндекс = ВходящийКонтекст.Индекс;
	НастройкиПодключения = ВходящийКонтекст.НастройкиПодключения;
	ПараметрыОперации = ВходящийКонтекст.ПараметрыОперации;
	
	Если ВходящийКонтекст.НастройкиПодключения.Количество() > ТекущийИндекс Тогда
		ВходящийКонтекст.Индекс = ВходящийКонтекст.Индекс + 1;
		ВходящийКонтекст.НастройкиПользователя = СервисКриптографииDSSКлиент.ПолучитьНастройкиПользователя(НастройкиПодключения[ТекущийИндекс], ПараметрыОперации);
		ПроверитьПодписьФоновымЗаданием(ВходящийКонтекст);
	Иначе
		РезультатВыполнения = ОтветСервисаПоУмолчанию(Ложь);
		РезультатВыполнения.КодОшибки = ВходящийКонтекст.КодОшибки;
		РезультатВыполнения.Ошибка = ВходящийКонтекст.Ошибка;
		РезультатВыполнения.СтатусОшибки = ВходящийКонтекст.СтатусОшибки;
		РезультатВыполнения.Вставить("НастройкиПользователя", ВходящийКонтекст.НастройкиПользователя);
		ПроверитьПодписьРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПроверитьПодпись.
Процедура ПроверитьПодписьФоновымЗаданием(ВходящийКонтекст)
	
	ОбъектОповещения = Новый ОписаниеОповещения("ПроверитьПодписьПослеВыполнения", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	НачатьЗамерВремени(ВходящийКонтекст);
		
	ОжидатьЗавершенияВыполненияВФоне(
		ОповещениеСледующее, 
		СервисКриптографииDSSСлужебныйВызовСервера.ПроверитьПодпись(
				ВходящийКонтекст.НастройкиПользователя,
				ВходящийКонтекст.ДанныеДокумента,
				ВходящийКонтекст.ИсходныйДокумент,
				ВходящийКонтекст.ТипПодписи,
				ВходящийКонтекст.СвойстваПроверки,
				ВходящийКонтекст.Сертификат,
				ВходящийКонтекст.ПараметрыОперации),
	ВходящийКонтекст.ПараметрыОперации);
	
КонецПроцедуры

// Продолжение процедуры ПроверитьПодпись.
Процедура ПроверитьПодписьПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ПроверитьПодписьРезультат(РезультатВыполнения, ВходящийКонтекст);
	Иначе
		ВходящийКонтекст.КодОшибки = РезультатВыполнения.КодОшибки;
		ВходящийКонтекст.Ошибка = РезультатВыполнения.Ошибка;
		ВходящийКонтекст.СтатусОшибки = РезультатВыполнения.СтатусОшибки;
		ПроверитьПодписьПоОчереди(ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры ПроверитьПодпись.
Процедура ПроверитьПодписьРезультат(РезультатВызова, ВходящийКонтекст)
	
	ПодготовленныйРезультат = ПодготовитьПсевдонимыОтвета(РезультатВызова, ВходящийКонтекст.ПараметрыОперации);
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова, ПодготовленныйРезультат);
	
КонецПроцедуры

#КонецОбласти

#Область ПолучитьЗаписиАудита

// Запускает цикл получения записей аудита действий пользователя на сервере
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. запуск фонового задания для получения записей аудита
// 4. проверка успешности окончания операции
// 5. сохранение нового токена для сеанса, возврат массива записей аудита.
//
Процедура ПолучитьЗаписиАудита(НастройкиПользователя, 
			ОповещениеОЗавершении, 
			Фильтры,
			НачальнаяПозиция,
			КонечнаяПозиция,
			ПараметрыОперации) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Получений выборки записей аудита'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("Фильтры", Фильтры);
	ПараметрыЦикла.Вставить("НачальнаяПозиция", НачальнаяПозиция);
	ПараметрыЦикла.Вставить("КонечнаяПозиция", КонечнаяПозиция);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ПолучитьЗаписиАудитаФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла, Ложь);
	
КонецПроцедуры	

// Продолжение процедуры ПолучитьЗаписиАудита.
Процедура ПолучитьЗаписиАудитаФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПолучитьЗаписиАудитаПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		ОжидатьЗавершенияВыполненияВФоне(
			ОповещениеСледующее, 
			СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьЗаписиАудита(
					ВходящийКонтекст.НастройкиПользователя,
					ВходящийКонтекст.Фильтры, 
					ВходящийКонтекст.НачальнаяПозиция, 
					ВходящийКонтекст.КонечнаяПозиция, 
					ВходящийКонтекст.ПараметрыОперации),
		ВходящийКонтекст.ПараметрыОперации);
	Иначе
		ПолучитьЗаписиАудитаРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;				
	
КонецПроцедуры

// Продолжение процедуры ПолучитьЗаписиАудита.
Процедура ПолучитьЗаписиАудитаПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ПолучитьЗаписиАудитаРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ПолучитьЗаписиАудитаРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПолучитьЗаписиАудитаФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		ПолучитьЗаписиАудитаРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПолучитьЗаписиАудита.
Процедура ПолучитьЗаписиАудитаРезультат(РезультатВызова, ВходящийКонтекст)
	
	ПодготовленныйРезультат = ПодготовитьПсевдонимыОтвета(РезультатВызова, ВходящийКонтекст.ПараметрыОперации);
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова, ПодготовленныйРезультат);
	
КонецПроцедуры

#КонецОбласти

#Область ОбработатьДокумент

// Универсальный цикл для сервиса обработки документов 
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. запуск фонового задания
// 4. проверка успешности окончания операции
// 5. сохранение нового токена для сеанса, возврат результата операции.
//
Процедура ОбработатьДокумент(
			НастройкиПользователя, 
			ОповещениеОЗавершении, 
			ВыполняемаяОперация,
			ПараметрыЗапроса,
			ДанныеДокумента,
			ПараметрыОперации) Экспорт
			
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Обработка документов'", КодЯзыка()) + ": " + ВыполняемаяОперация);
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ПараметрыЗапроса", ПараметрыЗапроса);
	ПараметрыЦикла.Вставить("ДанныеДокумента", ДанныеДокумента);
	ПараметрыЦикла.Вставить("ВыполняемоеДействие", ВыполняемаяОперация);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ОбработатьДокументФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла, Ложь);
			
КонецПроцедуры	

// Продолжение процедуры ОбработатьДокумент.
Процедура ОбработатьДокументФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ОбработатьДокументПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
		
		ВыполняемоеДействие = ВходящийКонтекст.ВыполняемоеДействие;
		
		Если ВыполняемоеДействие = "ЗагрузитьДокумент" Тогда
			ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.ЗагрузитьДокумент(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ДанныеДокумента, 
						ВходящийКонтекст.ПараметрыЗапроса, 
						ВходящийКонтекст.ПараметрыОперации);
		ИначеЕсли ВыполняемоеДействие = "ЗагрузитьПакетДокументов" Тогда
			ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.ЗагрузитьПакетДокументов(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ПараметрыЗапроса, 
						ВходящийКонтекст.ПараметрыОперации);
		ИначеЕсли ВыполняемоеДействие = "ИнформацияОДокументеПоИдентификатору" Тогда
			ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.ИнформацияОДокументеПоИдентификатору(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ПараметрыЗапроса, 
						ВходящийКонтекст.ПараметрыОперации);
		ИначеЕсли ВыполняемоеДействие = "ИнформацияОДокументеПоХешу" Тогда
			ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.ИнформацияОДокументеПоХешу(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ПараметрыЗапроса, 
						ВходящийКонтекст.ПараметрыОперации);
		ИначеЕсли ВыполняемоеДействие = "ПолучитьОбработанныйДокумент" Тогда
			ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьОбработанныйДокумент(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ПараметрыЗапроса, 
						ВходящийКонтекст.ПараметрыОперации);
		ИначеЕсли ВыполняемоеДействие = "ПолучитьОбработанныеДокументы" Тогда
			ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьОбработанныеДокументы(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ПараметрыЗапроса, 
						ВходящийКонтекст.ПараметрыОперации);
		ИначеЕсли ВыполняемоеДействие = "ИзменитьИнформациюОДокументе" Тогда
			ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.ИзменитьИнформациюОДокументе(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ДанныеДокумента, 
						ВходящийКонтекст.ПараметрыЗапроса, 
						ВходящийКонтекст.ПараметрыОперации);
		ИначеЕсли ВыполняемоеДействие = "ПривязатьДокумент" Тогда
			ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.ПривязатьДокумент(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ПараметрыЗапроса, 
						ВходящийКонтекст.ДанныеДокумента, 
						ВходящийКонтекст.ПараметрыОперации);
		ИначеЕсли ВыполняемоеДействие = "СконвертироватьДокумент" Тогда
			ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.СконвертироватьДокумент(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ПараметрыЗапроса, 
						ВходящийКонтекст.ПараметрыОперации);
		ИначеЕсли ВыполняемоеДействие = "ПолучитьИнформациюДокументаКонвертации" Тогда
			ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьИнформациюДокументаКонвертации(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ПараметрыЗапроса, 
						ВходящийКонтекст.ПараметрыОперации);
		ИначеЕсли ВыполняемоеДействие = "УдалитьДокумент" Тогда
			ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.УдалитьДокумент(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ПараметрыЗапроса, 
						ВходящийКонтекст.ПараметрыОперации);
		КонецЕсли;
					
		ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, ДействияНаСервере, ВходящийКонтекст.ПараметрыОперации);
		
	Иначе
		ОбработатьДокументРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	КонецЕсли;				
	
КонецПроцедуры

// Продолжение процедуры ОбработатьДокумент.
Процедура ОбработатьДокументПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбработатьДокументРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ОбработатьДокументРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ОбработатьДокументФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		ОбработатьДокументРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ОбработатьДокумент.
Процедура ОбработатьДокументРезультат(РезультатВызова, ВходящийКонтекст)
	
	ПодготовленныйРезультат = ПодготовитьПсевдонимыОтвета(РезультатВызова, ВходящийКонтекст.ПараметрыОперации);
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова, ПодготовленныйРезультат);
	
КонецПроцедуры

#КонецОбласти

#Область ОперацияСЗакрытомКлючом

// Запускает цикл операции с закрытым ключом
// Данная процедура может быть запущена как интерактивно, 
// так а в "тихом" режиме, если переданы подготовленные данные для создания
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 4. открытие формы запроса установки пин-кода (по необходимости)
// 7. выполнение основной операции с закрытым ключом 
// 8. сохранение нового токена для сеанса, возврат результат операции.
//
Процедура ОперацияСЗакрытомКлючом(НастройкиПользователя,
			ОповещениеОЗавершении,
			ВыполняемаяОперация,
			ПараметрыВыполнения,
			ПараметрыОперации) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Операция с закрытым ключом'", КодЯзыка()) + ": " + ВыполняемаяОперация);
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	ПараметрыЦикла.Вставить("ВыполняемоеДействие", ВыполняемаяОперация);
	ПараметрыЦикла.Вставить("ПараметрыВыполнения", ПараметрыВыполнения);
	ПараметрыЦикла.Вставить("ПинКод", СвойствоСтруктуры(ПараметрыВыполнения, "ПинКод"));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ОперацияСЗакрытомКлючомВводПинКода", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла, Ложь);
	
КонецПроцедуры

// Продолжение процедуры ОперацияСЗакрытомКлючом.
Процедура ОперацияСЗакрытомКлючомВводПинКода(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ПинКод = ВходящийКонтекст.ПинКод;
		РежимПинКода = ВходящийКонтекст.НастройкиПользователя.Политика.РежимПинКода <> "Запрещено";
		ВыполняемоеДействие = ВходящийКонтекст.ВыполняемоеДействие;
		
		Если ПинКод = Неопределено И РежимПинКода И ВыполняемоеДействие = "СоздатьЗакрытыйКлюч" Тогда
			ОбъектОповещения = Новый ОписаниеОповещения("ОперацияСЗакрытомКлючомПослеВводаПинКода", ЭтотОбъект);
			ОбработчикСледующий = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			ОткрытьФормуСменыПароля(ВходящийКонтекст.НастройкиПользователя, ОбработчикСледующий, "Установка", РежимПинКода = "Обязательно", ВходящийКонтекст.ПараметрыОперации);
		ИначеЕсли ПинКод = Неопределено Тогда
			ВходящийКонтекст.ПинКод = "";
			ОперацияСЗакрытомКлючомФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст);
		Иначе
			ОперацияСЗакрытомКлючомФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст);
		КонецЕсли;	
				
	Иначе
		ОперацияСЗакрытомКлючомРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры ОперацияСЗакрытомКлючом.
Процедура ОперацияСЗакрытомКлючомПослеВводаПинКода(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ВходящийКонтекст.ПинКод = РезультатВыполнения.НовыйПинКод;
		ОперацияСЗакрытомКлючомФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст);
	Иначе
		ОперацияСЗакрытомКлючомРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры	

// Продолжение процедуры ОперацияСЗакрытомКлючом.
Процедура ОперацияСЗакрытомКлючомФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст)
	
	Если РезультатВыполнения.Выполнено Тогда
		
		ОбъектОповещения = Новый ОписаниеОповещения("ОперацияСЗакрытомКлючомПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		ВыполняемоеДействие = ВходящийКонтекст.ВыполняемоеДействие;
		ПараметрыВыполнения = ВходящийКонтекст.ПараметрыВыполнения;
		ДействияНаСервере = Неопределено;
		
		Если ВыполняемоеДействие = "СоздатьЗакрытыйКлюч" Тогда
			ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.СоздатьЗакрытыйКлюч(
						ВходящийКонтекст.НастройкиПользователя,
						ПараметрыВыполнения.ИдентификаторАлгоритмаКлюча, 
						ПараметрыВыполнения.ПараметрыКлюча, 
						ВходящийКонтекст.ПинКод, 
						ВходящийКонтекст.ПараметрыОперации);
		Иначе
			
			ТекущийСертификат = СервисКриптографииDSSКлиентСервер.НайтиСертификат(ВходящийКонтекст.НастройкиПользователя, ПараметрыВыполнения.ИдентификаторСертификата);
			
			Если НЕ ЗначениеЗаполнено(ТекущийСертификат.Отпечаток) Тогда
				РезультатОтвета = ОтветСервисаПоУмолчанию(Ложь);
				ПолучитьОписаниеОшибки(РезультатОтвета,
									"certificate_not_found", 
									НСтр("ru = 'При установке параметра закрытого ключа'", КодЯзыка()));
				ОперацияСЗакрытомКлючомРезультат(РезультатОтвета, ВходящийКонтекст);
				
			ИначеЕсли ВыполняемоеДействие = "УстановитьПараметрЗакрытогоКлюча" Тогда
				ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.УстановитьПараметрЗакрытогоКлюча(
							ВходящийКонтекст.НастройкиПользователя,
							ТекущийСертификат.Идентификатор, 
							ПараметрыВыполнения.ИмяПараметра, 
							ПараметрыВыполнения.ЗначениеПараметра, 
							ВходящийКонтекст.ПараметрыОперации);
							
			ИначеЕсли ВыполняемоеДействие = "ПолучитьПараметрЗакрытогоКлюча" Тогда
				ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьПараметрЗакрытогоКлюча(
							ВходящийКонтекст.НастройкиПользователя,
							ТекущийСертификат.Идентификатор, 
							ПараметрыВыполнения.ИмяПараметра, 
							ВходящийКонтекст.ПараметрыОперации);
							
			КонецЕсли;
			
		КонецЕсли;
		
		Если ДействияНаСервере <> Неопределено Тогда
			ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, ДействияНаСервере, ВходящийКонтекст.ПараметрыОперации);
		КонецЕсли;	
		
	Иначе
		ОперацияСЗакрытомКлючомРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры ОперацияСЗакрытомКлючом.
Процедура ОперацияСЗакрытомКлючомПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ОперацияСЗакрытомКлючомРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ОперацияСЗакрытомКлючомРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПодписатьФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		ОперацияСЗакрытомКлючомРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ОперацияСЗакрытомКлючом.
Процедура ОперацияСЗакрытомКлючомРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область ДанныеОпераций

// Универсальный цикл для сервиса обработки операций 
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя
// 3. запуск фонового задания для получения записей аудита
// 4. проверка успешности окончания операции
// 5. сохранение нового токена для сеанса, возврат результата операции.
//
Процедура ДанныеОпераций(
			НастройкиПользователя, 
			ОповещениеОЗавершении, 
			ВыполняемаяОперация,
			ИдентификаторОперации,
			ПараметрыОперации) Экспорт
			
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Данные операций'", КодЯзыка()) + ": " + ВыполняемаяОперация);
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ИдентификаторОперации", ИдентификаторОперации);
	ПараметрыЦикла.Вставить("ВыполняемоеДействие", ВыполняемаяОперация);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ДанныеОперацийФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла, Ложь);
			
КонецПроцедуры	

// Продолжение процедуры ДанныеОпераций.
Процедура ДанныеОперацийФоновымЗаданием(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ДанныеОперацийПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
		
		ВыполняемоеДействие = ВходящийКонтекст.ВыполняемоеДействие;
		
		Если ВыполняемоеДействие = "СведенияОбОперации" Тогда
			ДействияНаСервере = СервисКриптографииDSSСлужебныйВызовСервера.СведенияОбОперации(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ИдентификаторОперации, 
						ВходящийКонтекст.ПараметрыОперации);
		КонецЕсли;
					
		ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, ДействияНаСервере, ВходящийКонтекст.ПараметрыОперации);
		
	Иначе
		ДанныеОперацийРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	КонецЕсли;				
	
КонецПроцедуры

// Продолжение процедуры ДанныеОпераций.
Процедура ДанныеОперацийПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ДанныеОперацийРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
		ДанныеОперацийРезультат(РезультатВыполнения, ВходящийКонтекст);
	ИначеЕсли СервисКриптографииDSSКлиентСервер.ЭтоОшибкаАутентификации(РезультатВыполнения.Ошибка) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ДанныеОперацийФоновымЗаданием", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст, Истина);
	Иначе
		ДанныеОперацийРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ДанныеОпераций.
Процедура ДанныеОперацийРезультат(РезультатВызова, ВходящийКонтекст)
	
	ПодготовленныйРезультат = ПодготовитьПсевдонимыОтвета(РезультатВызова, ВходящийКонтекст.ПараметрыОперации);
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова, ПодготовленныйРезультат);
	
КонецПроцедуры

#КонецОбласти

#Область ВыборСертификата

// Запускает цикл интерактивного выбора сертификата
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя, вложенный процесс
// 3. открыть форму выбора сертификата
// 4. возврат результат выбора.
//
Процедура ВыборСертификата(НастройкиПользователя, ОповещениеОЗавершении, ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Выбор сертификата'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	ПараметрыЦикла.Вставить("ПолноеОписаниеСертификата", СвойствоСтруктуры(ПараметрыОперации, "ПолноеОписаниеСертификата", Ложь));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ВыборСертификатаВыбор", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
	
КонецПроцедуры

// Продолжение процедуры ВыборСертификата.
Процедура ВыборСертификатаВыбор(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	ПроверитьТокенНаОбновление(РезультатВыполнения, ВходящийКонтекст.НастройкиПользователя);
	ВходящийКонтекст.Вставить("МаркерОбновлен", РезультатВыполнения.МаркерОбновлен);
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ВыборСертификатаРезультат", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ОткрытьФормуВыбораСертификата(ВходящийКонтекст.НастройкиПользователя, 
									ОповещениеСледующее,
									"Сертификаты",
									ВходящийКонтекст.ПолноеОписаниеСертификата,
									ВходящийКонтекст.ПараметрыОперации);
	Иначе
		ВыборСертификатаРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры ВыборСертификата.
Процедура ВыборСертификатаРезультат(РезультатВызова, ВходящийКонтекст) Экспорт
	
	РезультатВызова.МаркерОбновлен = ВходящийКонтекст.МаркерОбновлен;
	Если РезультатВызова.МаркерОбновлен Тогда
		РезультатВызова.Вставить("НастройкиПользователя", ВходящийКонтекст.НастройкиПользователя);
	КонецЕсли;	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область ПоказатьСертификат

// Запускает цикл для получения сведений о сертификате
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя, вложенный процесс
// 3. фоновым заданием получает сведения о сертификата
// 4. открыть форму просмотра сведений о сертификате
// 5. возврат результата успеха.
//
Процедура ПоказатьСертификат(НастройкиПользователя, ОповещениеОЗавершении, Сертификат, ПараметрыОперации = Неопределено) Экспорт

	ВходящиеПараметры = ПроверитьПараметрыОперации(ПараметрыОперации);
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Показать сведения сертификата'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении",ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя",НастройкиПользователя);
	ПараметрыЦикла.Вставить("Сертификат", 			Сертификат);
	ПараметрыЦикла.Вставить("ПараметрыОперации", 	ВходящиеПараметры);
	ПараметрыЦикла.Вставить("ПоказатьСведениеСервиса", СвойствоСтруктуры(ВходящиеПараметры, "ПоказатьСведениеСервиса", Ложь));
	ПараметрыЦикла.Вставить("ФормаВладелец",	 	СвойствоСтруктуры(ВходящиеПараметры, "ФормаВладелец"));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ПоказатьСертификатФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
	
КонецПроцедуры

// Продолжение процедуры ПоказатьСертификат.
Процедура ПоказатьСертификатФоновымЗаданием(РезультатВызова, ВходящийКонтекст) Экспорт

	ПроверитьТокенНаОбновление(РезультатВызова, ВходящийКонтекст.НастройкиПользователя);
	ВходящийКонтекст.Вставить("МаркерОбновлен", РезультатВызова.МаркерОбновлен);
	
	Если РезультатВызова.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПоказатьСертификатПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
		
		Если ВходящийКонтекст.ПоказатьСведениеСервиса Тогда
			ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьСвойстваСертификата(
					ВходящийКонтекст.НастройкиПользователя,
					ВходящийКонтекст.Сертификат);
		Иначе	
			ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьДанныеСертификата(
					ВходящийКонтекст.НастройкиПользователя,
					ВходящийКонтекст.Сертификат);
		КонецЕсли;
			
		ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, ОбработкаОперации, ВходящийКонтекст.ПараметрыОперации);
	Иначе				
		ПоказатьСертификатРезультат(РезультатВызова, ВходящийКонтекст);
	КонецЕсли;			
	
КонецПроцедуры

// Продолжение процедуры ПоказатьСертификат.
Процедура ПоказатьСертификатПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ТекущийСертификат 	= СервисКриптографииDSSКлиентСервер.НайтиСертификат(ВходящийКонтекст.НастройкиПользователя, ВходящийКонтекст.Сертификат);
		ОбъектОповещения 	= Новый ОписаниеОповещения("ПоказатьСертификатРезультат", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		
		ПараметрыФормы		= Новый Структура();
		ПараметрыФормы.Вставить("СведенияСертификата", ТекущийСертификат);
		ПараметрыФормы.Вставить("РежимПросмотра", "Сертификат");
		
		Если ВходящийКонтекст.ПоказатьСведениеСервиса Тогда
			ПараметрыФормы.Вставить("АдресСертификата", ПоместитьВоВременноеХранилище(РезультатВыполнения.Результат));
		Иначе
			ПараметрыФормы.Вставить("АдресСертификата", ПоместитьВоВременноеХранилище(РезультатВыполнения.Результат.Сертификат));
		КонецЕсли;	
		
		ОткрытьФормуСертификата(ВходящийКонтекст.НастройкиПользователя, 
				ОповещениеСледующее, 
				ПараметрыФормы, 
				ВходящийКонтекст.ФормаВладелец,
				ВходящийКонтекст.ПараметрыОперации);
	Иначе
		ПоказатьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
		
КонецПроцедуры

// Продолжение процедуры ПоказатьСертификат.
Процедура ПоказатьСертификатРезультат(РезультатВызова, ВходящийКонтекст) Экспорт
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
		
КонецПроцедуры

#КонецОбласти

#Область ПоказатьЗапросНаСертификат

// Запускает цикл для получения сведений о запросе на сертификат
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя, вложенный процесс
// 3. фоновым заданием получает сведения о сертификата
// 4. открыть форму просмотра сведений о сертификате
// 5. возврат результата успеха.
//
Процедура ПоказатьЗапросНаСертификат(НастройкиПользователя, ОповещениеОЗавершении, ЗапросНаСертификат, ПараметрыОперации = Неопределено) Экспорт

	ВходящиеПараметры = ПроверитьПараметрыОперации(ПараметрыОперации);
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Показать сведения запроса на сертификат'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении",ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя",НастройкиПользователя);
	ПараметрыЦикла.Вставить("ЗапросНаСертификат", 	ЗапросНаСертификат);
	ПараметрыЦикла.Вставить("ПараметрыОперации", 	ВходящиеПараметры);
	ПараметрыЦикла.Вставить("ФормаВладелец",	 	СвойствоСтруктуры(ВходящиеПараметры, "ФормаВладелец"));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ПоказатьЗапросНаСертификатФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
	
КонецПроцедуры

// Продолжение процедуры ПоказатьЗапросНаСертификат.
Процедура ПоказатьЗапросНаСертификатФоновымЗаданием(РезультатВызова, ВходящийКонтекст) Экспорт

	ПроверитьТокенНаОбновление(РезультатВызова, ВходящийКонтекст.НастройкиПользователя);
	ВходящийКонтекст.Вставить("МаркерОбновлен", РезультатВызова.МаркерОбновлен);
	
	Если РезультатВызова.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПоказатьЗапросНаСертификатПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		Если ТипЗнч(ВходящийКонтекст.ЗапросНаСертификат) = Тип("Число") Тогда
			НачатьЗамерВремени(ВходящийКонтекст);
			
			ОбработкаОперации = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьЗапросНаСертификат(
					ВходящийКонтекст.НастройкиПользователя,
					ВходящийКонтекст.ЗапросНаСертификат);
					
			ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, ОбработкаОперации, ВходящийКонтекст.ПараметрыОперации);
			
		Иначе
			ОтветСервиса = ОтветСервисаПоУмолчанию(Истина);
			ОтветСервиса.Вставить("Результат", ВходящийКонтекст.ЗапросНаСертификат);
			ВыполнитьОбработкуОповещения(ОповещениеСледующее, ОтветСервиса);
			
		КонецЕсли;			
			
	Иначе				
		ПоказатьЗапросНаСертификатРезультат(РезультатВызова, ВходящийКонтекст);
	КонецЕсли;			
	
КонецПроцедуры

// Продолжение процедуры ПоказатьЗапросНаСертификат.
Процедура ПоказатьЗапросНаСертификатПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		ВходящийКонтекст.ПараметрыОперации.Вставить("ПоказатьСведениеСервиса", Истина);
		ОбъектОповещения 	= Новый ОписаниеОповещения("ПоказатьЗапросНаСертификатРезультат", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		
		ПараметрыФормы		= Новый Структура();
		ПараметрыФормы.Вставить("АдресСертификата", ПоместитьВоВременноеХранилище(РезультатВыполнения.Результат.Содержание));
		ПараметрыФормы.Вставить("РежимПросмотра", "ЗапросНаСертификат");
		
		ОткрытьФормуСертификата(ВходящийКонтекст.НастройкиПользователя, 
				ОповещениеСледующее, 
				ПараметрыФормы, 
				ВходящийКонтекст.ФормаВладелец,
				ВходящийКонтекст.ПараметрыОперации);
	Иначе
		ПоказатьЗапросНаСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;	
		
КонецПроцедуры

// Продолжение процедуры ПоказатьЗапросНаСертификат.
Процедура ПоказатьЗапросНаСертификатРезультат(РезультатВызова, ВходящийКонтекст) Экспорт
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
		
КонецПроцедуры

#КонецОбласти

#Область СохранитьДанныеВФайл

// Запускает цикл для сохранения файла на стороне клиента
// Добавлена возможность вызова диалога для пользователя
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. вложенный процесс проверки установки расширения для работы с 1С:Предприятием
// 3. открыть диалог выбора файла, по необходимости
// 4. подготовка данных к записи (двоичные данные)
// 5. запись файла, асинхронным методом 
// 6. возврат результата операции.
//
Процедура СохранитьДанныеВФайл(ОповещениеОЗавершении, ДанныеФайла, ИмяФайла, ВыборФайла = Ложь, ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении",ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("ДанныеФайла", 			ДанныеФайла);
	ПараметрыЦикла.Вставить("ИмяФайла",				ИмяФайла);
	ПараметрыЦикла.Вставить("НуженВыборФайла",		ВыборФайла);
	ПараметрыЦикла.Вставить("ВидОперации", 			НСтр("ru = 'При записи файла'", КодЯзыка()) + ": " + ИмяФайла);
	ПараметрыЦикла.Вставить("ПараметрыОперации",	ПроверитьПараметрыОперации(ПараметрыОперации));
	
	СохранитьДанныеВФайлПроверитьРасширение(Неопределено, ПараметрыЦикла);
	
КонецПроцедуры	

// Продолжение процедуры СохранитьДанныеВФайл.
Процедура СохранитьДанныеВФайлПроверитьРасширение(РезультатВыполнения, ВходящийКонтекст)
	
	ОбъектОповещения = Новый ОписаниеОповещения("СохранитьДанныеВФайлПослеУстановкиРасширения", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	
	ТекстСообщения = НСтр("ru = 'Для продолжения работы требуется установить расширение для работы с 1С:Предприятием.'", КодЯзыка());
	
	ФайловаяСистемаКлиент.ПодключитьРасширениеДляРаботыСФайлами(ОповещениеСледующее, ТекстСообщения, Ложь);
	
КонецПроцедуры

// Продолжение процедуры СохранитьДанныеВФайл.
Процедура СохранитьДанныеВФайлПослеУстановкиРасширения(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения Тогда
		Если ВходящийКонтекст.НуженВыборФайла Тогда
			ОбъектОповещения = Новый ОписаниеОповещения("СохранитьДанныеВФайлПослеВыбораФайла", ЭтотОбъект);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			ЭтоРасширение	= Лев(ВходящийКонтекст.ИмяФайла, 1) = ".";
			ДиалогВыбора	= Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
			Если ЭтоРасширение Тогда
				ДиалогВыбора.Расширение = Сред(ВходящийКонтекст.ИмяФайла, 2);
				ДиалогВыбора.Фильтр 	= "(*" + ВходящийКонтекст.ИмяФайла + ")|*" + ВходящийКонтекст.ИмяФайла;
			Иначе
				ДиалогВыбора.ПолноеИмяФайла = ВходящийКонтекст.ИмяФайла;
			КонецЕсли;
			ДиалогВыбора.МножественныйВыбор = Ложь;
			ФайловаяСистемаКлиент.ПоказатьДиалогВыбора(ОповещениеСледующее, ДиалогВыбора);
		Иначе
			СохранитьДанныеВФайлПодготовитьДанные(ВходящийКонтекст);	
		КонецЕсли;
	Иначе
		ОтветВызова = ОтветСервисаПоУмолчанию(Ложь, "УстановкаРасширенияСФайлами");
		СохранитьДанныеВФайлРезультат(ОтветВызова, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры СохранитьДанныеВФайл.
Процедура СохранитьДанныеВФайлПослеВыбораФайла(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения <> Неопределено Тогда
		ВходящийКонтекст.ИмяФайла = РезультатВыполнения[0];
		СохранитьДанныеВФайлПодготовитьДанные(ВходящийКонтекст);
	Иначе
		ОтветВызова = ОтветСервисаПоУмолчанию(Ложь, "ОтказПользователя");
		СохранитьДанныеВФайлРезультат(ОтветВызова, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры СохранитьДанныеВФайл.
Процедура СохранитьДанныеВФайлПодготовитьДанные(ВходящийКонтекст)
	
	ДанныеФайла = ВходящийКонтекст.ДанныеФайла;
	ТипДанных 	= ТипЗнч(ВходящийКонтекст.ДанныеФайла);
	ЭтоДвоичные	= Ложь;
	
	Если ТипДанных = Тип("Строка") Тогда
		Если ЭтоАдресВременногоХранилища(ДанныеФайла) Тогда
			ДанныеФайла = ПолучитьИзВременногоХранилища(ДанныеФайла);
			ТипДанных	= ТипЗнч(ДанныеФайла);
		КонецЕсли;
	КонецЕсли;
	
	Если ТипДанных = Тип("ДвоичныеДанные") Тогда
		ЭтоДвоичные	= Истина;
	КонецЕсли;
	
	Если ТипДанных = Тип("Строка") Тогда
		Если СтрНайти(ДанныеФайла, ".") > 0 Тогда
			ОбъектОповещения = Новый ОписаниеОповещения("СохранитьДанныеВФайлПриПолученииДвоичныхДанных", ЭтотОбъект);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			НачатьСозданиеДвоичныхДанныхИзФайла(ОповещениеСледующее, ДанныеФайла);
			ЭтоДвоичные	= Истина;
			Возврат;
		Иначе
			ДанныеФайла = ПолучитьДвоичныеДанныеИзBase64Строки(ДанныеФайла);
			ЭтоДвоичные	= Истина;
		КонецЕсли;	
	КонецЕсли;
	
	Если ЭтоДвоичные Тогда
		СохранитьДанныеВФайлПриПолученииДвоичныхДанных(ДанныеФайла, ВходящийКонтекст);
	Иначе
		ОтветВызова = ОтветСервисаПоУмолчанию(Ложь, "ОшибкаВыполнения");
		СохранитьДанныеВФайлРезультат(ОтветВызова, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры СохранитьДанныеВФайл.
Процедура СохранитьДанныеВФайлПриПолученииДвоичныхДанных(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения <> Неопределено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("СохранитьДанныеВФайлПослеЗаписи", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		РезультатВыполнения.НачатьЗапись(ОповещениеСледующее, ВходящийКонтекст.ИмяФайла);
	Иначе
		ОтветВызова = ОтветСервисаПоУмолчанию(Ложь, "ОшибкаВыполнения");
		СохранитьДанныеВФайлРезультат(ОтветВызова, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры СохранитьДанныеВФайл.
Процедура СохранитьДанныеВФайлПослеЗаписи(ВходящийКонтекст) Экспорт
	
	ОтветВызова = ОтветСервисаПоУмолчанию();
	ОтветВызова.Вставить("Результат", ВходящийКонтекст.ИмяФайла);
	
	СохранитьДанныеВФайлРезультат(ОтветВызова, ВходящийКонтекст);
	
КонецПроцедуры

// Продолжение процедуры СохранитьДанныеВФайл.
Процедура СохранитьДанныеВФайлРезультат(РезультатВыполнения, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВыполнения);
	
КонецПроцедуры

#КонецОбласти

#Область ЗагрузитьДанныеИзФайла

// Запускает цикл для загрузки данных из файла на стороне клиента
// Добавлена возможность вызова диалога для пользователя
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. вложенный процесс проверки установки расширения для работы с 1С:Предприятием
// 3. открыть диалог выбора файла, по необходимости
// 4. получение данных файла, асинхронным методом 
// 5. возврат результата операции (адрес хранилища или двоичные данные).
//
Процедура ЗагрузитьДанныеИзФайла(ОповещениеОЗавершении, ИмяФайла, АдресХранилища, ВыборФайла = Ложь, ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении",ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("АдресХранилища",		АдресХранилища);
	ПараметрыЦикла.Вставить("ИмяФайла",				ИмяФайла);
	ПараметрыЦикла.Вставить("НуженВыборФайла",		ВыборФайла);
	ПараметрыЦикла.Вставить("ПараметрыОперации",	ПроверитьПараметрыОперации(ПараметрыОперации));
	ПараметрыЦикла.Вставить("ВидОперации", 			НСтр("ru = 'При загрузке файла'", КодЯзыка()) + ": " + ИмяФайла);
		
	ЗагрузитьДанныеИзФайлаПроверитьРасширение(Неопределено, ПараметрыЦикла);
	
КонецПроцедуры	

// Продолжение процедуры ЗагрузитьДанныеИзФайла.
Процедура ЗагрузитьДанныеИзФайлаПроверитьРасширение(РезультатВыполнения, ВходящийКонтекст)
	
	ОбъектОповещения = Новый ОписаниеОповещения("ЗагрузитьДанныеИзФайлаПослеУстановкиРасширения", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	
	ТекстСообщения = НСтр("ru = 'Для продолжения работы требуется установить расширение для работы с 1С:Предприятием.'", КодЯзыка());
	
	ФайловаяСистемаКлиент.ПодключитьРасширениеДляРаботыСФайлами(ОповещениеСледующее, ТекстСообщения, Ложь);
	
КонецПроцедуры

// Продолжение процедуры ЗагрузитьДанныеИзФайла.
Процедура ЗагрузитьДанныеИзФайлаПослеУстановкиРасширения(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения Тогда
		Если ВходящийКонтекст.НуженВыборФайла Тогда
			ОбъектОповещения = Новый ОписаниеОповещения("ЗагрузитьДанныеИзФайлаПослеВыбораФайла", ЭтотОбъект);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			ЭтоРасширение = Лев(ВходящийКонтекст.ИмяФайла, 1) = ".";
			ДиалогВыбора = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
			Если ЭтоРасширение Тогда
				ДиалогВыбора.Расширение = Сред(ВходящийКонтекст.ИмяФайла, 2);
				ДиалогВыбора.Фильтр 	= "(*" + ВходящийКонтекст.ИмяФайла + ")|*" + ВходящийКонтекст.ИмяФайла;
			Иначе
				ДиалогВыбора.ПолноеИмяФайла = ВходящийКонтекст.ИмяФайла;
			КонецЕсли;
			ДиалогВыбора.МножественныйВыбор = Ложь;
			ФайловаяСистемаКлиент.ПоказатьДиалогВыбора(ОповещениеСледующее, ДиалогВыбора);
		Иначе
			ЗагрузитьДанныеИзФайлаПодготовитьДанные(Неопределено, ВходящийКонтекст);	
		КонецЕсли;
	Иначе
		ОтветВызова = ОтветСервисаПоУмолчанию(Ложь, "УстановкаРасширенияСФайлами");
		ЗагрузитьДанныеИзФайлаРезультат(ОтветВызова, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры ЗагрузитьДанныеИзФайла.
Процедура ЗагрузитьДанныеИзФайлаПослеВыбораФайла(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения <> Неопределено Тогда
		ВходящийКонтекст.ИмяФайла = РезультатВыполнения[0];
		ЗагрузитьДанныеИзФайлаПодготовитьДанные(Неопределено, ВходящийКонтекст);
	Иначе
		ОтветВызова = ОтветСервисаПоУмолчанию(Ложь, "ОтказПользователя");
		ЗагрузитьДанныеИзФайлаРезультат(ОтветВызова, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры ЗагрузитьДанныеИзФайла.
Процедура ЗагрузитьДанныеИзФайлаПодготовитьДанные(РезультатВыполнения, ВходящийКонтекст)
	
	ОбъектОповещения = Новый ОписаниеОповещения("ЗагрузитьДанныеИзФайлаПослеПолученииДвоичныхДанных", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	НачатьСозданиеДвоичныхДанныхИзФайла(ОповещениеСледующее, ВходящийКонтекст.ИмяФайла);
	
КонецПроцедуры

// Продолжение процедуры ЗагрузитьДанныеИзФайла.
Процедура ЗагрузитьДанныеИзФайлаПослеПолученииДвоичныхДанных(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	РезультатВызова = ОтветСервисаПоУмолчанию();
	Если РезультатВыполнения <> Неопределено Тогда
		Результат = Новый Структура();
		Результат.Вставить("ИмяФайла", ВходящийКонтекст.ИмяФайла);
		Результат.Вставить("ДанныеФайла", "");
		
		Если ЗначениеЗаполнено(ВходящийКонтекст.АдресХранилища) Тогда
			ПоместитьВоВременноеХранилище(РезультатВыполнения, ВходящийКонтекст.АдресХранилища);
			Результат.ДанныеФайла = ВходящийКонтекст.АдресХранилища;
		Иначе
			Результат.ДанныеФайла = РезультатВыполнения;
		КонецЕсли;
		РезультатВызова.Вставить("Результат", Результат);
	Иначе
		РезультатВызова.Выполнено = Ложь;
		ПолучитьОписаниеОшибки(РезультатВызова, "ПолучениеФайла");
	КонецЕсли;
	
	ЗагрузитьДанныеИзФайлаРезультат(РезультатВызова, ВходящийКонтекст);
	
КонецПроцедуры

// Продолжение процедуры ЗагрузитьДанныеИзФайла.
Процедура ЗагрузитьДанныеИзФайлаРезультат(РезультатВыполнения, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВыполнения);
	
КонецПроцедуры

#КонецОбласти

#Область ПоказатьСостояниеУчетнойЗаписи

// Запускает цикл интерактивного отображения состояние учетной записи
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя, вложенный процесс
// 3. открыть форму отображения состояния учетной записи
// 4. возврат результат успеха.
//
Процедура ПоказатьСостояниеУчетнойЗаписи(НастройкиПользователя, ОповещениеОЗавершении, ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Показать состояние учетной записи'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	ПараметрыЦикла.Вставить("ФорматРезультата", СвойствоСтруктуры(ПараметрыОперации, "ФорматРезультата"));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ПоказатьСостояниеУчетнойЗаписиОтобразить", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
	
КонецПроцедуры

// Продолжение процедуры ПоказатьСостояниеУчетнойЗаписи.
Процедура ПоказатьСостояниеУчетнойЗаписиОтобразить(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	ПроверитьТокенНаОбновление(РезультатВыполнения, ВходящийКонтекст.НастройкиПользователя);
	ВходящийКонтекст.Вставить("МаркерОбновлен", РезультатВыполнения.МаркерОбновлен);
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПоказатьСостояниеУчетнойЗаписиРезультат", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		Если ВходящийКонтекст.ФорматРезультата = "XML" Тогда
			
			ОжидатьЗавершенияВыполненияВФоне(
				ОповещениеСледующее, 
				СервисКриптографииDSSСлужебныйВызовСервера.СостояниеУчетнойЗаписи(
						ВходящийКонтекст.НастройкиПользователя,
						ВходящийКонтекст.ПараметрыОперации),
			ВходящийКонтекст.ПараметрыОперации);
			
		Иначе	
			ОткрытьФормуСостоянияУчетнойЗаписи(ВходящийКонтекст.НастройкиПользователя, ОповещениеСледующее, ВходящийКонтекст.ПараметрыОперации);
		КонецЕсли;	
	Иначе
		ПоказатьСостояниеУчетнойЗаписиРезультат(РезультатВыполнения, ВходящийКонтекст);			
	КонецЕсли			
	
КонецПроцедуры

// Продолжение процедуры ПоказатьСостояниеУчетнойЗаписи.
Процедура ПоказатьСостояниеУчетнойЗаписиРезультат(РезультатВызова, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(РезультатВызова, ВходящийКонтекст);
	
	РезультатВыполнения.МаркерОбновлен = ВходящийКонтекст.МаркерОбновлен;
	Если РезультатВыполнения.МаркерОбновлен Тогда
		РезультатВызова.Вставить("НастройкиПользователя", ВходящийКонтекст.НастройкиПользователя);
	КонецЕсли;
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВыполнения);

КонецПроцедуры

#КонецОбласти

#Область ОбновитьПолитикуПользователя

// Запускает цикл принудительного обновления информации о политике настроек учетной записи
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя, принудительная авторизация, вложенный процесс
// 3. запуск фонового получение новых значений политики
// 4. обновления токена авторизации, возврат результат успеха.
//
Процедура ОбновитьПолитикуПользователя(НастройкиПользователя, ОповещениеОЗавершении, ПараметрыОперации = Неопределено) Экспорт

	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Обновить политику пользователя'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении",ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя",НастройкиПользователя);
	ПараметрыЦикла.Вставить("ПараметрыОперации", 	ПроверитьПараметрыОперации(ПараметрыОперации));
	ПараметрыЦикла.Вставить("ОбновилиПолитики", 	НастройкиПользователя = Неопределено);
	
	ОбъектОповещения = Новый ОписаниеОповещения("ОбновитьПолитикуПользователяФоновымЗаданием", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла, , Истина);
	
КонецПроцедуры

// Продолжение процедуры ОбновитьПолитикуПользователя.
Процедура ОбновитьПолитикуПользователяФоновымЗаданием(РезультатВызова, ВходящийКонтекст) Экспорт

	ПроверитьТокенНаОбновление(РезультатВызова, ВходящийКонтекст.НастройкиПользователя);
	ВходящийКонтекст.Вставить("МаркерОбновлен", РезультатВызова.МаркерОбновлен);
	
	Если РезультатВызова.Выполнено 
		И НЕ ВходящийКонтекст.ОбновилиПолитики Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ОбновитьПолитикуПользователяПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		НачатьЗамерВремени(ВходящийКонтекст);
			
		ОжидатьЗавершенияВыполненияВФоне(
			ОповещениеСледующее, 
			СервисКриптографииDSSСлужебныйВызовСервера.ОбновитьПолитикуПользователя(
					ВходящийКонтекст.НастройкиПользователя,
					ВходящийКонтекст.ПараметрыОперации),
			ВходящийКонтекст.ПараметрыОперации);
	Иначе				
		ОбновитьПолитикуПользователяРезультат(РезультатВызова, ВходящийКонтекст);
	КонецЕсли;			
	
КонецПроцедуры

// Продолжение процедуры ОбновитьПолитикуПользователя.
Процедура ОбновитьПолитикуПользователяПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВыполнения.Выполнено Тогда
		НовыеНастройки = РезультатВыполнения.НастройкиПользователя;
		СервисКриптографииDSSСлужебныйВызовСервера.ОбновитьНастройкиПользователя(ВходящийКонтекст.НастройкиПользователя, НовыеНастройки);
	КонецЕсли;	
	ПроверитьТокенНаОбновление(РезультатВыполнения, ВходящийКонтекст.НастройкиПользователя, Истина);
	ОбновитьПолитикуПользователяРезультат(РезультатВыполнения, ВходящийКонтекст);
		
КонецПроцедуры

// Продолжение процедуры ОбновитьПолитикуПользователя.
Процедура ОбновитьПолитикуПользователяРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
		
КонецПроцедуры

#КонецОбласти

#Область ОткрытьСведенияУчетнойЗаписи

// Запускает цикл открытия формы элемента справочника Учетные записи
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. открыть форму элемента
// 3. возврат результат успеха.
//
Процедура ОткрытьСведенияУчетнойЗаписи(ОповещениеОЗавершении, СсылкаУчетнойЗаписи, ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Открыть сведения учетной записи'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("СсылкаУчетнойЗаписи", СсылкаУчетнойЗаписи);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	Если ИспользованиеОблачнойПодписиВозможно(ПараметрыЦикла) Тогда
		ОткрытьСведенияУчетнойЗаписиОтобразить(Неопределено, ПараметрыЦикла);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ОткрытьСведенияУчетнойЗаписи.
Процедура ОткрытьСведенияУчетнойЗаписиОтобразить(РезультатВыполнения, ВходящийКонтекст)
	
	ОбъектОповещения = Новый ОписаниеОповещения("ОткрытьСведенияУчетнойЗаписиРезультат", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	ОткрытьФормуСведенийУчетнойЗаписи(ОповещениеСледующее, ВходящийКонтекст.СсылкаУчетнойЗаписи, ВходящийКонтекст.ПараметрыОперации);
	
КонецПроцедуры

// Продолжение процедуры ОткрытьСведенияУчетнойЗаписи.
Процедура ОткрытьСведенияУчетнойЗаписиРезультат(РезультатВызова, ВходящийКонтекст) Экспорт
	
	Если РезультатВызова.Выполнено Тогда
		// надо поменять параметры сеанса
		Оповестить("ИзменилосьСостояниеУчетнойЗаписи", ВходящийКонтекст.СсылкаУчетнойЗаписи);
	КонецЕсли;
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область ВывестиОшибку

// Запускает цикл отображения формы с ошибкой
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. открыть форму ошибки
// 3. возврат результат успеха.
//
Процедура ВывестиОшибку(ОповещениеОЗавершении, ТекстОшибки = "", ЭтоКодОшибки = Ложь, ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Вывести ошибку сервиса'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("ТекстОшибки", ТекстОшибки);
	ПараметрыЦикла.Вставить("ЭтоКодОшибки", ЭтоКодОшибки);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ВывестиОшибкуОтобразить(ПараметрыЦикла);
	
КонецПроцедуры

// Продолжение процедуры ВывестиОшибку.
Процедура ВывестиОшибкуОтобразить(ВходящийКонтекст)
	
	ОбъектОповещения = Новый ОписаниеОповещения("ВывестиОшибкуРезультат", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	ОтобразитьОшибкуПользователю(ОповещениеСледующее, 
			ВходящийКонтекст.ТекстОшибки, 
			ВходящийКонтекст.ЭтоКодОшибки, 
			ВходящийКонтекст.ПараметрыОперации);
	
КонецПроцедуры

// Продолжение процедуры ВывестиОшибку.
Процедура ВывестиОшибкуРезультат(РезультатВызова, ВходящийКонтекст) Экспорт
	
	Если ВходящийКонтекст.ОповещениеОЗавершении <> Неопределено Тогда
		Если ВходящийКонтекст.ПараметрыОперации.Количество() > 0 Тогда
			ВыполнитьОбработкуОповещения(ВходящийКонтекст.ОповещениеОЗавершении, ВходящийКонтекст.ПараметрыОперации);
		Иначе
			ВыполнитьОбработкуОповещения(ВходящийКонтекст.ОповещениеОЗавершении, РезультатВызова);
		КонецЕсли;	
	КонецЕсли;

КонецПроцедуры

#КонецОбласти

#Область ВывестиИнформацию

// Запускает цикл отображения формы с ошибкой
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. открыть форму ошибки
// 3. возврат результат успеха.
//
Процедура ВывестиИнформацию(ОповещениеОЗавершении, ТекстСообщения, ТаймАут = Неопределено, Заголовок = "", ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Вывести информацию пользователю'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("ТекстСообщения", ТекстСообщения);
	ПараметрыЦикла.Вставить("ТаймАут", ТаймАут);
	ПараметрыЦикла.Вставить("Заголовок", Заголовок);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ВывестиИнформациюОтобразить(ПараметрыЦикла);
	
КонецПроцедуры

// Продолжение процедуры ВывестиИнформацию.
Процедура ВывестиИнформациюОтобразить(ВходящийКонтекст)
	
	ОбъектОповещения = Новый ОписаниеОповещения("ВывестиИнформациюРезультат", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	ОтобразитьИнформациюПользователю(ОповещениеСледующее, 
			ВходящийКонтекст.ТекстСообщения, 
			ВходящийКонтекст.ТаймАут, 
			ВходящийКонтекст.Заголовок, 
			ВходящийКонтекст.ПараметрыОперации);
	
КонецПроцедуры

// Продолжение процедуры ВывестиИнформацию.
Процедура ВывестиИнформациюРезультат(РезультатВызова, ВходящийКонтекст) Экспорт
	
	Если ВходящийКонтекст.ОповещениеОЗавершении <> Неопределено Тогда
		Если ВходящийКонтекст.ПараметрыОперации.Количество() > 0 Тогда
			ВыполнитьОбработкуОповещения(ВходящийКонтекст.ОповещениеОЗавершении, ВходящийКонтекст.ПараметрыОперации);
		Иначе
			ВыполнитьОбработкуОповещения(ВходящийКонтекст.ОповещениеОЗавершении, РезультатВызова);
		КонецЕсли;	
	КонецЕсли;

КонецПроцедуры

#КонецОбласти

#Область ВывестиВопрос

// Запускает цикл отображения формы с ошибкой
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. открыть форму ошибки
// 3. возврат результат успеха.
//
Процедура ВывестиВопрос(ОповещениеОЗавершении, ТекстСообщения, СписокКоманд, ТаймАут = Неопределено, Заголовок = "", ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Вопрос пользователю'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("ТекстСообщения", ТекстСообщения);
	ПараметрыЦикла.Вставить("СписокКоманд", СписокКоманд);
	ПараметрыЦикла.Вставить("ТаймАут", ТаймАут);
	ПараметрыЦикла.Вставить("Заголовок", Заголовок);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ВывестиВопросОтобразить(ПараметрыЦикла);
	
КонецПроцедуры

// Продолжение процедуры ВывестиИнформацию.
Процедура ВывестиВопросОтобразить(ВходящийКонтекст)
	
	ОбъектОповещения = Новый ОписаниеОповещения("ВывестиВопросРезультат", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	ОтобразитьВопросПользователю(ОповещениеСледующее, 
			ВходящийКонтекст.ТекстСообщения, 
			ВходящийКонтекст.СписокКоманд,
			ВходящийКонтекст.ТаймАут, 
			ВходящийКонтекст.Заголовок, 
			ВходящийКонтекст.ПараметрыОперации);
	
КонецПроцедуры

// Продолжение процедуры ВывестиИнформацию.
Процедура ВывестиВопросРезультат(РезультатВызова, ВходящийКонтекст) Экспорт
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);

КонецПроцедуры

#КонецОбласти

#Область ПолучитьОписаниеСервиса

// Запускает цикл получения данных сервиса обнаружения
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя, вложенный процесс
// 3. запуск фонового задания для получения данных
// 4. возврат результат операции.
//
Процедура ПолучитьОписаниеСервиса(ОповещениеОЗавершении, АдресСервиса = "", ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Получение описание сервиса'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("АдресСервиса", АдресСервиса);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	Если ИспользованиеОблачнойПодписиВозможно(ПараметрыЦикла) Тогда
		ПолучитьОписаниеСервисаФоновымЗаданием(Неопределено, ПараметрыЦикла);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры ПолучитьОписаниеСервиса.
Процедура ПолучитьОписаниеСервисаФоновымЗаданием(РезультатВызова, ВходящийКонтекст)

	ОбъектОповещения = Новый ОписаниеОповещения("ПолучитьОписаниеСервисаПослеВыполнения", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	НачатьЗамерВремени(ВходящийКонтекст);
	
	ОжидатьЗавершенияВыполненияВФоне(
		ОповещениеСледующее, 
		СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьОписаниеСервиса(
				ВходящийКонтекст.АдресСервиса,
				ВходящийКонтекст.ПараметрыОперации),
		ВходящийКонтекст.ПараметрыОперации);
	
КонецПроцедуры

// Продолжение процедуры ПолучитьОписаниеСервиса.
Процедура ПолучитьОписаниеСервисаПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	ПолучитьОписаниеСервисаРезультат(РезультатВыполнения, ВходящийКонтекст);
		
КонецПроцедуры

// Продолжение процедуры ПолучитьОписаниеСервиса.
Процедура ПолучитьОписаниеСервисаРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
		
КонецПроцедуры

#КонецОбласти

#Область ВыбратьНастройкиСервиса

// Запускает цикл интерактивного выбора настроек подключения к сервису
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. вложенный процесс получения сведений о настройках сервера
// 3. открытие формы выбора настроек
// 4. возврат результат операции.
//
Процедура ВыбратьНастройкиСервиса(ОповещениеОЗавершении, АдресСервиса = "", ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Выбор настроек из описания сервиса'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("АдресСервиса", АдресСервиса);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	Если ИспользованиеОблачнойПодписиВозможно(ПараметрыЦикла) Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ВыбратьНастройкиСервисаПослеВыполнения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
			
		ПолучитьОписаниеСервиса(ОповещениеСледующее,
					ПараметрыЦикла.АдресСервиса,
					ПараметрыЦикла.ПараметрыОперации);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры ВыбратьНастройкиСервиса.
Процедура ВыбратьНастройкиСервисаПослеВыполнения(ДлительнаяОперация, ВходящийКонтекст) Экспорт
	
	РезультатВызова = ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст);
	
	Если РезультатВызова.Выполнено Тогда
		ОписаниеСервиса = РезультатВызова.Результат;
		ОбъектОповещения = Новый ОписаниеОповещения("ВыбратьНастройкиСервисаПослеВыбора", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ОткрытьФормуВыбораНастроекСервиса(ОписаниеСервиса, ОповещениеСледующее, ВходящийКонтекст.ПараметрыОперации);
	Иначе
		ВходящийКонтекст.ПараметрыОперации.Вставить("ОтобразитьОшибку", Ложь);
		ВыбратьНастройкиСервисаРезультат(РезультатВызова, ВходящийКонтекст);
	КонецЕсли;	
		
КонецПроцедуры

// Продолжение процедуры ВыбратьНастройкиСервиса.
Процедура ВыбратьНастройкиСервисаПослеВыбора(РезультатВызова, ВходящийКонтекст) Экспорт
	
	Если РезультатВызова.Выполнено Тогда
		АдресЦИ = СтрЗаменить(РезультатВызова.Результат.АдресЦИ, ВходящийКонтекст.АдресСервиса, "");
		АдресСЭП = СтрЗаменить(РезультатВызова.Результат.АдресСЭП, ВходящийКонтекст.АдресСервиса, "");
		
		Результат = Новый Структура();
		Результат.Вставить("СервисИдентификации", АдресЦИ);
		Результат.Вставить("СервисПодписи", АдресСЭП);
		РезультатВызова.Результат = Результат;
	КонецЕсли;
	
	ВыбратьНастройкиСервисаРезультат(РезультатВызова, ВходящийКонтекст);
	
КонецПроцедуры

// Продолжение процедуры ВыбратьНастройкиСервиса.
Процедура ВыбратьНастройкиСервисаРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
		
КонецПроцедуры

#КонецОбласти

#Область ПроверитьРаботоспособностьСервиса

// Запускает цикл интерактивного проверки работоспособности сервиса
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. проверка аутентификации пользователя, вложенный процесс
// 3. открытие формы проверки работоспособности
// 4. возврат результат операции.
//
Процедура ПроверитьРаботоспособностьСервиса(НастройкиПользователя, ОповещениеОЗавершении, СписокОпераций = Неопределено, ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Проверка работоспособности сервиса'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("СписокОпераций", СписокОпераций);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	ОбъектОповещения = Новый ОписаниеОповещения("ПроверитьРаботоспособностьПослеВыбора", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
	
КонецПроцедуры

// Продолжение процедуры ПроверитьРаботоспособностьСервиса.
Процедура ПроверитьРаботоспособностьПослеВыбора(РезультатВызова, ВходящийКонтекст) Экспорт
	
	ПроверитьТокенНаОбновление(РезультатВызова, ВходящийКонтекст.НастройкиПользователя);
	ВходящийКонтекст.Вставить("МаркерОбновлен", РезультатВызова.МаркерОбновлен);
	
	Если РезультатВызова.Выполнено Тогда
		ОбъектОповещения = Новый ОписаниеОповещения("ПроверитьРаботоспособностьРезультат", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ОткрытьФормуПроверкиРаботоспособности(ВходящийКонтекст.НастройкиПользователя, 
								ОповещениеСледующее,
								ВходящийКонтекст.СписокОпераций,
								ВходящийКонтекст.ПараметрыОперации);
	Иначе
		ПроверитьРаботоспособностьРезультат(РезультатВызова, ВходящийКонтекст);
	КонецЕсли;

КонецПроцедуры

// Продолжение процедуры ПроверитьРаботоспособностьСервиса.
Процедура ПроверитьРаботоспособностьРезультат(РезультатВызова, ВходящийКонтекст) Экспорт
	
	ПроверитьТокенНаОбновление(РезультатВызова, ВходящийКонтекст.НастройкиПользователя);
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область ОткрытьСведенияСервера

// Запускает цикл интерактивного открытия формы справочника Серверы облачной криптографии
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. открытие формы элемента справочника Серверы облачной криптографии
// 3. возврат результат операции.
//
Процедура ОткрытьСведенияСервера(ОповещениеОЗавершении, СсылкаСервера, ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Открыть сведения сервера'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("СсылкаСервера", СсылкаСервера);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	Если ИспользованиеОблачнойПодписиВозможно(ПараметрыЦикла) Тогда
		ОткрытьСведенияСервераОтобразить(Неопределено, ПараметрыЦикла);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры ОткрытьСведенияСервера.
Процедура ОткрытьСведенияСервераОтобразить(РезультатВызова, ВходящийКонтекст)
	
	ОбъектОповещения = Новый ОписаниеОповещения("ОткрытьСведенияСервераРезультат", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	ОткрытьФормуСведенийСервера(ОповещениеСледующее, ВходящийКонтекст.СсылкаСервера, ВходящийКонтекст.ПараметрыОперации);
	
КонецПроцедуры

// Продолжение процедуры ОткрытьСведенияСервера.
Процедура ОткрытьСведенияСервераРезультат(РезультатВызова, ВходящийКонтекст) Экспорт
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры	
	
#КонецОбласти

#Область ВыборЭкземпляраСервера

// Запускает цикл интерактивного выбора из списка справочника Серверы облачной криптографии
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. открытие формы списка выбора справочника Серверы облачной криптографии
// 3. возврат результат операции.
//
Процедура ВыборЭкземпляраСервера(ОповещениеОЗавершении, ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Выбор экземпляра сервера'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	
	Если ИспользованиеОблачнойПодписиВозможно(ПараметрыЦикла) Тогда
		ВыборЭкземпляраСервераОтобразить(Неопределено, ПараметрыЦикла);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры ВыборЭкземпляраСервера.
Процедура ВыборЭкземпляраСервераОтобразить(РезультатВызова, ВходящийКонтекст)
	
	ОбъектОповещения = Новый ОписаниеОповещения("ВыборЭкземпляраСервераРезультат", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	ОткрытьФормуВыбораЭкземпляраСервера(ОповещениеСледующее, ВходящийКонтекст.ПараметрыОперации);
	
КонецПроцедуры

// Продолжение процедуры ВыборЭкземпляраСервера.
Процедура ВыборЭкземпляраСервераРезультат(РезультатВызова, ВходящийКонтекст) Экспорт
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры	
	
#КонецОбласти

#Область ДобавлениеПрограммыЭлектроннойПодписи

Процедура ДобавлениеПрограммыЭлектроннойПодписи(ОповещениеОЗавершении = Неопределено, ПараметрыОперации = Неопределено) Экспорт
	
	ПараметрыЦикла = Новый Структура();
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	
	ОбъектОповещения = Новый ОписаниеОповещения("ДобавлениеПрограммыЭлектроннойПодписиПослеВыбора", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ОткрытьФормуВыборПрограммы(ОповещениеСледующее, ПроверитьПараметрыОперации(ПараметрыОперации));
	
КонецПроцедуры	

Процедура ДобавлениеПрограммыЭлектроннойПодписиПослеВыбора(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено 
		И ВходящийКонтекст.ОповещениеОЗавершении = Неопределено Тогда
		Если РезультатВыполнения.Результат = "ОблачнаяПодпись" Тогда
			ПараметрыФормы = ВходящийКонтекст.ПараметрыОперации;
			ПараметрыФормы.Вставить("РежимОткрытияОкна", РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
			ОткрытьСведенияУчетнойЗаписи(Неопределено, Неопределено, ВходящийКонтекст.ПараметрыОперации);
		Иначе	
			ОткрытьФорму("Справочник.ПрограммыЭлектроннойПодписиИШифрования.ФормаОбъекта");
		КонецЕсли;	
	КонецЕсли;			
	
	ДобавлениеПрограммыЭлектроннойПодписиРезультат(РезультатВыполнения, ВходящийКонтекст);			
	
КонецПроцедуры

Процедура ДобавлениеПрограммыЭлектроннойПодписиРезультат(РезультатВызова, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова);
	
КонецПроцедуры

#КонецОбласти

#Область РаботаСФоновымиЗаданиями

// Только для внутреннего использования.
Процедура ОжидатьЗавершенияВыполненияВФоне(ОповещениеОЗавершении, ДлительнаяОперация, ПараметрыОперации = Неопределено) Экспорт
	
	Если ДлительнаяОперация.Статус = "Выполняется" Тогда
		ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(Неопределено);
		ПараметрыОжидания.ВыводитьОкноОжидания = Ложь;
		
		ПояснениеОперации = СвойствоСтруктуры(ПараметрыОперации, "ПояснениеОперации", "");
		Если ЗначениеЗаполнено(ПояснениеОперации) Тогда
			ПараметрыОжидания.ТекстСообщения = ПояснениеОперации;
		КонецЕсли;
		
		ФормаВладелец = СвойствоСтруктуры(ПараметрыОперации, "ОжидатьВыполнения");
		Если ФормаВладелец = Ложь Тогда
			ПараметрыОжидания.ВыводитьОкноОжидания = Ложь;
		ИначеЕсли ФормаВладелец <> Неопределено Тогда
			ПараметрыОжидания.ВыводитьОкноОжидания = Истина;
			ПараметрыОжидания.ФормаВладелец = ?(ФормаВладелец = Истина, Неопределено, ФормаВладелец);
		КонецЕсли;	
		
		ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, ОповещениеОЗавершении, ПараметрыОжидания);
		
	Иначе
		ВыполнитьОбработкуОповещения(ОповещениеОЗавершении, ДлительнаяОперация);
		
	КонецЕсли;	

КонецПроцедуры

// Только для внутреннего использования.
//
// Возвращаемое значение:
//  Структура - ОтветСервисаПоУмолчанию
//
Функция ПолучитьРезультатВыполненияВФоне(ДлительнаяОперация, ВходящийКонтекст = Неопределено) Экспорт
	
	Ответ = ОтветСервисаПоУмолчанию(Ложь);
	ЗакончитьЗамерВремени(ВходящийКонтекст);
	
	ПараметрыОперации = СвойствоСтруктуры(ВходящийКонтекст, "ПараметрыОперации");
	НастройкиПользователя = СвойствоСтруктуры(ВходящийКонтекст, "НастройкиПользователя");
	
	Если ДлительнаяОперация = Неопределено Тогда
		Ответ.Ошибка = НСтр("ru = 'Работа сервиса DSS завершилась с ошибкой.'", КодЯзыка());
	ИначеЕсли ДлительнаяОперация.Свойство("Выполнено") Тогда
		Ответ = ДлительнаяОперация;
	ИначеЕсли ДлительнаяОперация.Статус = "Выполнено" Тогда
		Ответ = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьРезультатВыполненияФоновогоЗадания(ДлительнаяОперация.АдресРезультата, ПараметрыОперации);
	Иначе
		Ответ.Ошибка = НСтр("ru = 'Вызов API сервиса DSS завершился с ошибкой при выполнении.'", КодЯзыка()) 
						+ ДлительнаяОперация.КраткоеПредставлениеОшибки;
	КонецЕсли;
	
	МаркерОбновлен = СвойствоСтруктуры(Ответ, "МаркерОбновлен");

	Если НастройкиПользователя <> Неопределено И МаркерОбновлен <> Неопределено Тогда
		ПроверитьТокенНаОбновление(Ответ, ВходящийКонтекст.НастройкиПользователя);
	КонецЕсли;
	
	Возврат Ответ;
	
КонецФункции

Процедура ПодключитьФормуОжидания(ПараметрыОперации, НовыйРежим)
	
	ТекущийРежим = СвойствоСтруктуры(ПараметрыОперации, "ОжидатьВыполнения");
	Если ТекущийРежим = Неопределено Тогда
		ПараметрыОперации.Вставить("ОжидатьВыполнения", НовыйРежим);
	КонецЕсли;	
	
КонецПроцедуры

#КонецОбласти

#Область СлужебныеДляРаботыОписанийОповещения

Процедура ОшибкаПриРаботеСервиса(ИнформацияОбОшибке, СтандартнаяОбработка, ВходящийКонтекст) Экспорт
	
	СтандартнаяОбработка= Ложь;
	ОтветВызова 		= ОтветСервисаПоУмолчанию(Ложь);
	
	ТекстПользователя 	= ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке);
	ТекстЖурнала		= ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке);
	КодОшибки 			= СервисКриптографииDSSКлиентСервер.ПолучитьКодОшибки(ТекстПользователя);
	ВидОперации 		= СвойствоСтруктуры(ВходящийКонтекст, "ВидОперации");
	РегистрироватьОшибку= СвойствоСтруктуры(ВходящийКонтекст, "ПараметрыОперации.РегистрироватьОшибку", Истина);
	
	Если ЗначениеЗаполнено(ВидОперации) Тогда
		ТекстПользователя	= ТекстПользователя + Символы.ПС + НСтр("ru = 'Вид операции:'", КодЯзыка()) + " " + ВидОперации;
	КонецЕсли;	
	
	Если ЗначениеЗаполнено(КодОшибки) Тогда
		ОтветВызова.Ошибка 	= ТекстПользователя;
	Иначе
		ПолучитьОписаниеОшибки(ОтветВызова, "ОшибкаВыполнения", ТекстПользователя);
	КонецЕсли;
	
	НовыйОбъект = СервисКриптографииDSSКлиентСервер.ФильтроватьПараметрыВызова(ВходящийКонтекст);
	СервисКриптографииDSSСлужебныйВызовСервера.ЗаписатьОшибкуВЖурналРегистрации(ТекстЖурнала, НовыйОбъект, РегистрироватьОшибку);
	
	ВернутьРезультатВызова(ВходящийКонтекст, ОтветВызова);
		
КонецПроцедуры

// Только для внутреннего использования.
// 
// Возвращаемое значение:
//  Структура
//
Функция ПодготовитьПараметрыОперации(ПоказатьОшибку = Истина, ТекущаяСтруктура = Неопределено) Экспорт
	
	Если ТекущаяСтруктура = Неопределено Тогда
		Результат = Новый Структура();
	Иначе
		Результат = ТекущаяСтруктура;
	КонецЕсли;
	
	Результат.Вставить("ОтобразитьОшибку", ПоказатьОшибку);
	Результат.Вставить("ИдентификаторОперации", Неопределено);
	Результат.Вставить("ОжидатьВыполнения", Неопределено);
	
	Возврат Результат;
	
КонецФункции

#КонецОбласти

#Область РаботаСОшибкамиПоСуществу

// Только для внутреннего использования.
//
// Возвращаемое значение:
//  Строка
//
Функция СформироватьОтказАутентификации(РезультатОперации) Экспорт
	
	Результат = ПолучитьОписаниеОшибки(РезультатОперации, "Отказ");
	
	Возврат Результат;
	
КонецФункции

// Только для внутреннего использования.
// 
// Возвращаемое значение:
//  Строка
//
Функция ПолучитьОписаниеОшибки(РезультатОперации, ИдентификаторОшибки, Дополнение = "") Экспорт
	
	Результат = СервисКриптографииDSSКлиентСервер.ПолучитьОписаниеОшибки(РезультатОперации, ИдентификаторОшибки, Дополнение);
	
	Возврат Результат;
	
КонецФункции

#КонецОбласти

#Область РаботаСоСлужебнымиФормами

// Только для внутреннего использования.
Процедура ОткрытьЗаявлениеНаИзменение(ОповещениеОЗавершении, ПараметрыФормы, ПараметрыОперации = Неопределено) Экспорт
	
	ОткрытьФормуЗаявленияНаИзменение(ОповещениеОЗавершении, ПараметрыФормы, ПараметрыОперации);
	
КонецПроцедуры	

// Только для внутреннего использования.
Процедура ОткрытьПодборУчетныхЗаписей(ОповещениеОЗавершении, ПараметрыФормы, ПараметрыОперации = Неопределено) Экспорт

	ОткрытьФормуПодбораУчетныхЗаписей(ОповещениеОЗавершении, ПараметрыФормы, ПараметрыОперации);

КонецПроцедуры

// Только для внутреннего использования.
Процедура ПолучитьПодтверждениеПользователя(
				ОповещениеОЗавершении,
				ЗаголовокФормы,
				ТекстВопроса, 
				ПараметрыПечати = Неопределено,
				ОписаниеПодтверждения = "",
				ПараметрыОперации = Неопределено)
									
	ПараметрыФормы = Новый Структура();
	ПараметрыФормы.Вставить("Заголовок", ЗаголовокФормы);
	ПараметрыФормы.Вставить("ЗаголовокПодтверждения", ОписаниеПодтверждения);
	ПараметрыФормы.Вставить("ТекстВопроса", ТекстВопроса);
	
	Если ПараметрыПечати <> Неопределено Тогда
		ПараметрыФормы.Вставить("ПараметрыПечати", ПараметрыПечати);
		ПараметрыФормы.Вставить("Редактирование", Истина);
	КонецЕсли;
	
	СписокКоманд = Новый СписокЗначений;
	СписокКоманд.Добавить("КодВозвратаДиалога.ОК", НСтр("ru = 'Продолжить'"), Истина);
	СписокКоманд.Добавить("КодВозвратаДиалога.Отмена", НСтр("ru = 'Отмена'"));
	
	ПараметрыФормы.Вставить("СписокКоманд", СписокКоманд);
	
	Если ПараметрыОперации <> Неопределено Тогда
		ОбщегоНазначенияКлиентСервер.ДополнитьСтруктуру(ПараметрыФормы, ПараметрыОперации, Истина);
	КонецЕсли;	

	ОткрытьФормуПодтверждения(ОповещениеОЗавершении, ПараметрыФормы, ПараметрыОперации);
	
КонецПроцедуры

#КонецОбласти

#Область АктивироватьИУстановитьСертификат

// Внимание, для заявлений оформленные через УЦ 1С, не требуется установка сертификата.
// Необходимо обновить список сертификатов, через обновление политики
//
// Разделено на несколько шагов
// 1. Определение списка действий, проверка авторизации пользователя
// 2. Обновление кеша сертификатов
// 3. Расшифровка блока конф. информации при необходимости
// 4. Разбор конфиденциальных данных
// 5. Получение подтверждения от пользователя (отдельная форма) для действий
// 6. Активация ключа авторизации мобильного приложения
// 7. Отправка кода активации ключа мобильного приложения
// 8. Контрольное подписание для активирования пароля, активация пароля, сброс кеша настроек пользователя и повторная авторизация
// 9. Установка сертификата по необходимости (если переданы двоичные данные)
// 10. Проверка отправки расписки
// 11. Завершение цикла.
//
// Разбирает файл настроек заявления полученные от Калуги-Астрал, производит дополнительные действия.
//
// Параметры:
//  ОповещениеОЗавершении		- ОписаниеОповещения
//  ПараметрыВызова				- Структура:
//    * Сертификат 				- Строка
//    							- ДвоичныеДанные
//    * УчетнаяЗапись			- СправочникСсылка.УчетныеЗаписиDSS
//    * ШифрованныйБлок			- Строка
//    							- ДвоичныеДанные
//    * Расшифровывать			- Булево
//    * УстановитьСертификат	- Булево
//    * Действия				- Строка - идентификаторы через запятую
//  ПараметрыОперации 			- Структура
//
Процедура АктивироватьИУстановитьСертификат(ОповещениеОЗавершении, ПараметрыВызова, ПараметрыОперации = Неопределено) Экспорт
	
	УчетнаяЗапись = ПараметрыВызова.УчетнаяЗапись;
	Сертификат = ПараметрыВызова.Сертификат;
	ШифрованныйБлок = ПараметрыВызова.ШифрованныйБлок;
	Расшифровывать = СвойствоСтруктуры(ПараметрыВызова, "Расшифровывать", Истина);
	УстановитьСертификат = СвойствоСтруктуры(ПараметрыВызова, "УстановитьСертификат", Истина);
	ДействиеОблачнойПодписи = СвойствоСтруктуры(ПараметрыВызова, "Действия", "");
	Активизировать = СвойствоСтруктуры(ПараметрыВызова, "Активизировать", Ложь);
	
	НастройкиПользователя = СервисКриптографииDSSСлужебныйВызовСервера.ПолучитьНастройкиПользователя(УчетнаяЗапись, ПараметрыОперации);
	ДанныеСертификата = Неопределено;
	ИдентификаторКлючаСертификата = Неопределено;
	ОтпечатокСертификата = "";
	
	Если ЭтоАдресВременногоХранилища(ШифрованныйБлок) Тогда
		ШифрованныйБлок = ПолучитьИзВременногоХранилища(ШифрованныйБлок);
	КонецЕсли;
	
	Если ЭтоАдресВременногоХранилища(Сертификат) Тогда
		ДанныеСертификата = ПолучитьИзВременногоХранилища(Сертификат);
	ИначеЕсли ТипЗнч(Сертификат) = Тип("Строка") Тогда
		НашлиСертификат = СервисКриптографииDSSКлиентСервер.НайтиСертификат(НастройкиПользователя, Сертификат).Содержимое;
		Если ЗначениеЗаполнено(НашлиСертификат) Тогда
			ДанныеСертификата = ПолучитьДвоичныеДанныеИзBase64Строки(НашлиСертификат);
		КонецЕсли;
		УстановитьСертификат = Ложь;
	Иначе
		ДанныеСертификата = Сертификат;
	КонецЕсли;
	
	Если ЗначениеЗаполнено(ДанныеСертификата) Тогда
		СвойстваСертификата = СервисКриптографииDSSASNКлиентСервер.ПолучитьСвойстваСертификата(ДанныеСертификата);
		ИдентификаторКлючаСертификата = СвойстваСертификата.ИдентификаторСубъекта;
		ОтпечатокСертификата = СвойстваСертификата.Отпечаток;
	Иначе
		УстановитьСертификат = Ложь;
	КонецЕсли;	
	
	ДействиеОблачнойПодписи = СтрРазделить(ДействиеОблачнойПодписи, ",", Ложь);
	
	ДействиеАктивироватьПароль = ДействиеОблачнойПодписи.Найти("АктивироватьПароль") <> Неопределено;
	ДействиеАктивироватьКлючПриложения = ДействиеОблачнойПодписи.Найти("АктивироватьКлючПриложения") <> Неопределено;
	ДействиеПовторныйКлючПриложения = ДействиеОблачнойПодписи.Найти("КлючПриложения") <> Неопределено;
	ДействиеПолучитьКодАктивации = ДействиеОблачнойПодписи.Найти("ПолучитьКодАктивации") <> Неопределено;
	ДействиеПолучитьРасписку = ДействиеОблачнойПодписи.Найти("ОтправитьРасписку") <> Неопределено;
	Расшифровывать = Расшифровывать 
				И (ДействиеАктивироватьПароль ИЛИ ДействиеАктивироватьКлючПриложения 
				ИЛИ ДействиеПовторныйКлючПриложения ИЛИ ДействиеПолучитьКодАктивации);
	
	ВходящийКонтекст = Новый Структура;
	ВходящийКонтекст.Вставить("ИдентификаторДокументооборота", Строка(Новый УникальныйИдентификатор));
	ВходящийКонтекст.Вставить("ИдентификаторКлючаСертификата", ИдентификаторКлючаСертификата);
	ВходящийКонтекст.Вставить("Активизировать", Активизировать);
	ВходящийКонтекст.Вставить("ДанныеБлока", Неопределено);
	ВходящийКонтекст.Вставить("УчетнаяЗапись", УчетнаяЗапись);
	ВходящийКонтекст.Вставить("НастройкиПользователя", НастройкиПользователя);
	ВходящийКонтекст.Вставить("ШифрованныйБлок", ШифрованныйБлок);
	ВходящийКонтекст.Вставить("Расшифровывать", Расшифровывать);
	ВходящийКонтекст.Вставить("ТипОшибки", "ОбработкаНастроекЗаявления");
	ВходящийКонтекст.Вставить("ОтпечатокСертификата", ОтпечатокСертификата);
	ВходящийКонтекст.Вставить("УстановитьСертификат", УстановитьСертификат);
	ВходящийКонтекст.Вставить("ДанныеСертификата", ДанныеСертификата);
	ВходящийКонтекст.Вставить("Активировать", Ложь);
	ВходящийКонтекст.Вставить("ДействиеАктивироватьПароль", ДействиеАктивироватьПароль);
	ВходящийКонтекст.Вставить("ДействиеАктивироватьКлючПриложения", ДействиеАктивироватьКлючПриложения);
	ВходящийКонтекст.Вставить("ДействиеПовторныйКлючПриложения", ДействиеПовторныйКлючПриложения);
	ВходящийКонтекст.Вставить("ДействиеПолучитьКодАктивации", ДействиеПолучитьКодАктивации);
	ВходящийКонтекст.Вставить("ДействиеПолучитьРасписку", ДействиеПолучитьРасписку);
	ВходящийКонтекст.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	ВходящийКонтекст.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	
	ПараметрыВызова = Новый Структура;
	Если Активизировать Тогда
		ВходящийКонтекст.ПараметрыОперации.Вставить("ПарольПользователя", СервисКриптографииDSSКлиент.ПодготовитьОбъектПароля(""));
	КонецЕсли;	
	
	ОбъектОповещения = Новый ОписаниеОповещения("АктивироватьИУстановитьСертификатПослеПроверкиАвторизация", ЭтотОбъект, ВходящийКонтекст);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ВходящийКонтекст);
	
КонецПроцедуры

// Продолжение процедуры АктивироватьИУстановитьСертификат.
Процедура АктивироватьИУстановитьСертификатПослеПроверкиАвторизация(ОтветСервиса, ВходящийКонтекст) Экспорт
	
	НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
    ПараметрыОперации = ВходящийКонтекст.ПараметрыОперации;
	
	Если НЕ ОтветСервиса.Выполнено Тогда
		РезультатВыполнения = ОтветСервисаПоУмолчанию(Ложь);
		ПолучитьОписаниеОшибки(РезультатВыполнения,
							ВходящийКонтекст.ТипОшибки,
							НСтр("ru = 'Ошибка авторизации при установке сертификата в контейнер ключа и хранилище сертификатов сервиса DSS'", КодЯзыка()));
		АктивироватьИУстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст); 
		
	Иначе
		ОбъектОповещения = Новый ОписаниеОповещения("АктивироватьИУстановитьСертификатРасшифровать", ЭтотОбъект, ВходящийКонтекст);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		СервисКриптографииDSSКлиент.ОбновитьДанныеСертификатов(ОповещениеСледующее, НастройкиПользователя, ПараметрыОперации);
		
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры АктивироватьИУстановитьСертификат.
Процедура АктивироватьИУстановитьСертификатРасшифровать(ОтветСервиса, ВходящийКонтекст) Экспорт

	НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
	ШифрованныйБлок = ВходящийКонтекст.ШифрованныйБлок;
	Расшифровывать = ВходящийКонтекст.Расшифровывать;
    ПараметрыОперации = ВходящийКонтекст.ПараметрыОперации;
	
	Если НЕ ОтветСервиса.Выполнено Тогда
		РезультатВыполнения = ОтветСервисаПоУмолчанию(Ложь);
		ПолучитьОписаниеОшибки(РезультатВыполнения,
							ВходящийКонтекст.ТипОшибки,
							ОтветСервиса.Ошибка);
		АктивироватьИУстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	Иначе
		Если Расшифровывать И ЗначениеЗаполнено(ШифрованныйБлок) Тогда
			ОбъектОповещения = Новый ОписаниеОповещения("АктивироватьИУстановитьСертификатПослеРасшифровки", ЭтотОбъект, ВходящийКонтекст);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			СервисКриптографииDSSКлиент.Расшифровать(ОповещениеСледующее, НастройкиПользователя, ШифрованныйБлок, , , ПараметрыОперации);
		ИначеЕсли Расшифровывать Тогда
			ТекстОшибки = НСтр("ru = 'Блок конфиденциальных не заполнен'");
			РезультатВыполнения = ОтветСервисаПоУмолчанию(Истина);
			ПолучитьОписаниеОшибки(РезультатВыполнения, ВходящийКонтекст.ТипОшибки, ТекстОшибки);
			АктивироватьИУстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
		Иначе
		    АктивироватьИУстановитьСертификатПодтверждениеПользователя(ВходящийКонтекст);
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры АктивироватьИУстановитьСертификат.
Процедура АктивироватьИУстановитьСертификатПослеРасшифровки(ОтветСервиса, ВходящийКонтекст) Экспорт
	
	УчетнаяЗапись = ВходящийКонтекст.УчетнаяЗапись;
	ТекстОшибки = "";
	ДанныеБлока = Неопределено;
	
	Если ОтветСервиса.Выполнено Тогда
		КлючПоиска = СервисКриптографииDSSСлужебныйВызовСервера.КлючПоискаУчетнойЗаписи(УчетнаяЗапись);
		РезультатВызова = СервисКриптографииDSSСлужебныйВызовСервера.СлужебныеДанныеОблачнойПодписи(ОтветСервиса.Результат, КлючПоиска);
		Если НЕ РезультатВызова.Выполнено Тогда
			ТекстОшибки = НСтр("ru = 'Блок конфиденциальных данных поврежден'");
		Иначе
			ДанныеБлока = РезультатВызова;
		КонецЕсли;	
	Иначе
		ТекстОшибки = ОтветСервиса.Ошибка;
	КонецЕсли;
	
	Если ДанныеБлока = Неопределено Тогда
		РезультатВыполнения = ОтветСервисаПоУмолчанию(Ложь);
		ПолучитьОписаниеОшибки(РезультатВыполнения,
							ВходящийКонтекст.ТипОшибки,
							ТекстОшибки);
		АктивироватьИУстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст); 
	Иначе
		ВходящийКонтекст.ДанныеБлока = ДанныеБлока;
		АктивироватьИУстановитьСертификатПодтверждениеПользователя(ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры АктивироватьИУстановитьСертификат.
// 
// Параметры:
//  ВходящийКонтекст - Структура:
//    * НастройкиПользователя - см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//
Процедура АктивироватьИУстановитьСертификатПодтверждениеПользователя(ВходящийКонтекст)
	
	ДанныеБлока = ВходящийКонтекст.ДанныеБлока;
	НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
    ПараметрыОперации = ВходящийКонтекст.ПараметрыОперации;
	
	ОбъектОповещения = Новый ОписаниеОповещения("АктивироватьИУстановитьСертификатПослеПодтверждения", ЭтотОбъект, ВходящийКонтекст);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
	ЗаголовокПодтверждения = "";
	ОписаниеДействия = "";
	ПС = Символы.ПС;
	
	ПараметрыДляПечати = Новый Структура();
	ПараметрыДляПечати.Вставить("Сервер", НастройкиПользователя.Сервер);
	ПараметрыДляПечати.Вставить("Логин", НастройкиПользователя.Логин);
	
	Если ВходящийКонтекст.ДействиеАктивироватьПароль И ВходящийКонтекст.ДействиеАктивироватьКлючПриложения Тогда
		ПараметрыДляПечати.Вставить("ДанныеКлюча", ДанныеБлока.НовыйКлючПриложения);
		ПараметрыДляПечати.Вставить("Пароль", ДанныеБлока.Пароль);
		ЗаголовокПодтверждения = НСтр("ru = 'Подтверждаю получение пароля и QR-кода, содержащий вектора аутентификации.'");
		ОписаниеДействия = НСтр("ru = 'Необходимо завершить настройки для подключения к серверу DSS'")
							+ НСтр("ru = 'и мобильного приложения.'") + ПС 
							+ " - " + НСтр("ru = 'запомните или сохраните полученный пароль для подключения'") + ПС
							+ " - " + НСтр("ru = 'отсканируйте в мобильном приложении полученный QR-код'") + ПС
							+ " - " + НСтр("ru = 'подтвердите получение пароля и QR-кода'") + ПС
							+ " - " + НСтр("ru = 'введите в мобильном приложении высланный в SMS или по почте код активации'") + ПС
							+ " - " + НСтр("ru = 'подключитесь к серверу DSS с новым паролем'") + ПС
							+ " - " + НСтр("ru = 'с помощью мобильного приложения выполните операцию контрольной подписи'");
	ИначеЕсли ВходящийКонтекст.ДействиеАктивироватьПароль Тогда
		ПараметрыДляПечати.Вставить("Пароль", ДанныеБлока.Пароль);
		ЗаголовокПодтверждения = НСтр("ru = 'Подтверждаю получение пароля.'");
		ОписаниеДействия = НСтр("ru = 'Необходимо завершить настройки для подключения к серверу DSS.'") + ПС 
							+ " - " + НСтр("ru = 'запомните или сохраните полученный пароль для подключения'") + ПС
							+ " - " + НСтр("ru = 'подтвердите получение пароля'") + ПС
							+ " - " + НСтр("ru = 'с помощью мобильного приложения выполните операцию контрольной подписи'") + ПС
							+ " - " + НСтр("ru = 'подключитесь к серверу DSS с новым паролем'");
	ИначеЕсли ВходящийКонтекст.ДействиеАктивироватьКлючПриложения Тогда
		ПараметрыДляПечати.Вставить("ДанныеКлюча", ДанныеБлока.НовыйКлючПриложения);
		ЗаголовокПодтверждения = НСтр("ru = 'Подтверждаю получение QR-кода, содержащий вектор аутентификации.'");
		ОписаниеДействия = НСтр("ru = 'Необходимо завершить настройки для подключения мобильного приложения.'") + ПС 
							+ " - " + НСтр("ru = 'отсканируйте в мобильном приложении полученный QR-код'") + ПС
							+ " - " + НСтр("ru = 'подтвердите получение QR-кода'") + ПС
							+ " - " + НСтр("ru = 'введите в мобильном приложении высланный в SMS или по почте код активации'");
	ИначеЕсли ВходящийКонтекст.ДействиеПовторныйКлючПриложения Тогда
		ПараметрыДляПечати.Вставить("ДанныеКлюча", ДанныеБлока.КлючПриложения);
		ЗаголовокПодтверждения = НСтр("ru = 'Подтверждаю получение QR-кода, содержащий вектора аутентификации.'");
		ОписаниеДействия = НСтр("ru = 'Необходимо повторно настроить подключение мобильного приложения.'") + ПС 
							+ " - " + НСтр("ru = 'отсканируйте в мобильном приложении полученный QR-код'") + ПС
							+ " - " + НСтр("ru = 'подтвердите получение QR-кода'") + ПС
							+ " - " + НСтр("ru = 'введите в мобильном приложении высланный в SMS или по почте код активации'");
	КонецЕсли;
	
	Если ЗначениеЗаполнено(ОписаниеДействия) Тогда
		ПолучитьПодтверждениеПользователя(ОповещениеСледующее,
					НСтр("ru = 'Параметры подключения к серверу DSS'"),
					ОписаниеДействия,
					ПараметрыДляПечати, 
					ЗаголовокПодтверждения,
					ПараметрыОперации);
	Иначе
		ВыполнитьОбработкуОповещения(ОповещениеСледующее, КодВозвратаДиалога.ОК);
	КонецЕсли;				
	
КонецПроцедуры

// Продолжение процедуры АктивироватьИУстановитьСертификат.
Процедура АктивироватьИУстановитьСертификатПослеПодтверждения(ОтветСервиса, ВходящийКонтекст) Экспорт

	ДанныеБлока = ВходящийКонтекст.ДанныеБлока;
	
	Если ОтветСервиса = КодВозвратаДиалога.ОК Тогда
		Если ВходящийКонтекст.ДействиеАктивироватьКлючПриложения Тогда
			ДлительнаяОперация = СервисКриптографииDSSСлужебныйВызовСервера.ОбменССерверомАктивироватьКлючПриложенияУчетнойЗаписи(ДанныеБлока.ПодписьПриложения, ВходящийКонтекст.ИдентификаторКлючаСертификата);
			ОбъектОповещения = Новый ОписаниеОповещения("АктивироватьИУстановитьСертификатОтправитьКод", ЭтотОбъект, ВходящийКонтекст);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, ДлительнаяОперация);
			
		Иначе
			РезультатВыполнения = ОтветСервисаПоУмолчанию(Истина);
			АктивироватьИУстановитьСертификатОтправитьКод(РезультатВыполнения, ВходящийКонтекст);
			
		КонецЕсли;
	Иначе
		РезультатВыполнения = ОтветСервисаПоУмолчанию(Ложь);
		ПолучитьОписаниеОшибки(РезультатВыполнения,
							ВходящийКонтекст.ТипОшибки,
							НСтр("ru = 'Пользователь отказался от продолжения настроек заявления'"));
		АктивироватьИУстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст); 
		
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры АктивироватьИУстановитьСертификат.
Процедура АктивироватьИУстановитьСертификатОтправитьКод(ОтветСервиса, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ОтветСервиса, ВходящийКонтекст);
	ДанныеБлока = ВходящийКонтекст.ДанныеБлока;
	
	Если НЕ РезультатВыполнения.Выполнено Тогда
		РезультатВыполнения = ОтветСервисаПоУмолчанию(Ложь);
		ПолучитьОписаниеОшибки(РезультатВыполнения,
							ВходящийКонтекст.ТипОшибки,
							НСтр("ru = 'Не удалось выполнить контрольную подпись'"));
		АктивироватьИУстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст); 
	ИначеЕсли ВходящийКонтекст.ДействиеПолучитьКодАктивации Тогда
		ДлительнаяОперация = СервисКриптографииDSSСлужебныйВызовСервера.ОбменССерверомОтправитьКодАктивацииКлюча(ВходящийКонтекст.ИдентификаторКлючаСертификата, ДанныеБлока.ПодписьКодаАктивации);
		ОбъектОповещения = Новый ОписаниеОповещения("АктивироватьИУстановитьСертификатАктивироватьПарольУчетнойЗаписи", ЭтотОбъект, ВходящийКонтекст);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, ДлительнаяОперация);
	Иначе
		АктивироватьИУстановитьСертификатАктивироватьПарольУчетнойЗаписи(ОтветСервисаПоУмолчанию(Истина), ВходящийКонтекст);
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры АктивироватьИУстановитьСертификат.
Процедура АктивироватьИУстановитьСертификатАктивироватьПарольУчетнойЗаписи(ОтветСервиса, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ОтветСервиса, ВходящийКонтекст);
	
	НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
	ДанныеБлока = ВходящийКонтекст.ДанныеБлока;
	ОтпечатокСертификата = ВходящийКонтекст.ОтпечатокСертификата;
    ПараметрыОперации = ВходящийКонтекст.ПараметрыОперации;
	
	Если ОтветСервиса.Выполнено Тогда
		Если ВходящийКонтекст.ДействиеАктивироватьПароль Тогда
			СвойстваСертификата = Новый Структура("Отпечаток", ОтпечатокСертификата);
			ДанныеДляПодписи = ПолучитьДвоичныеДанныеИзСтроки(ДанныеБлока.ПодписьПароля);
			
			СвойстваПодписи = СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиCMS(Истина, Ложь);
			СервисКриптографииDSSКлиентСервер.ПолучитьИнформациюДокументаДляПодписи(СвойстваПодписи, НСтр("ru = 'Контрольная подпись'"), "txt");
			
			ПараметрыОперации = Новый Структура;
			ПараметрыОперации.Вставить("ПодтверждатьПринудительно", Истина);

			ОбъектОповещения = Новый ОписаниеОповещения("АктивироватьИУстановитьСертификатПослеПодписи", ЭтотОбъект, ВходящийКонтекст);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			СервисКриптографииDSSКлиент.Подписать(ОповещениеСледующее, НастройкиПользователя, ДанныеДляПодписи, СвойстваПодписи, СвойстваСертификата, ПараметрыОперации);
			
		Иначе
			АктивироватьИУстановитьСертификатПроверитьСертификат(ОтветСервисаПоУмолчанию(Истина), ВходящийКонтекст); 
		КонецЕсли;
	Иначе
		РезультатВыполнения = ОтветСервисаПоУмолчанию(Ложь);
		ПолучитьОписаниеОшибки(РезультатВыполнения,
							ВходящийКонтекст.ТипОшибки,
							НСтр("ru = 'Не удалось выполнить контрольную подпись'"));
		АктивироватьИУстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст); 
		
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры АктивироватьИУстановитьСертификат.
Процедура АктивироватьИУстановитьСертификатПослеПодписи(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	ДанныеБлока = ВходящийКонтекст.ДанныеБлока;
	
	Если РезультатВыполнения.Выполнено Тогда
		ДлительнаяОперация = СервисКриптографииDSSСлужебныйВызовСервера.ОбменССерверомАктивироватьУчетнуюЗапись(
								ВходящийКонтекст.ИдентификаторКлючаСертификата, 
								ДанныеБлока.ПодписьПароля,
								РезультатВыполнения.Результат);
		ОбъектОповещения = Новый ОписаниеОповещения("АктивироватьИУстановитьСертификатПослеАктивированияПароля", ЭтотОбъект, ВходящийКонтекст);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ОжидатьЗавершенияВыполненияВФоне(ОповещениеСледующее, ДлительнаяОперация);
		
	Иначе
		РезультатВыполнения = ОтветСервисаПоУмолчанию(Ложь);
		ПолучитьОписаниеОшибки(РезультатВыполнения,
							ВходящийКонтекст.ТипОшибки,
							НСтр("ru = 'Не удалось выполнить контрольную подпись'"));
		АктивироватьИУстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст); 
		
	КонецЕсли;	
	
КонецПроцедуры

// Продолжение процедуры АктивироватьИУстановитьСертификат.
Процедура АктивироватьИУстановитьСертификатПослеАктивированияПароля(ОтветСервиса, ВходящийКонтекст) Экспорт
	
	РезультатВыполнения = ПолучитьРезультатВыполненияВФоне(ОтветСервиса, ВходящийКонтекст);
	
	НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения 	= Новый ОписаниеОповещения("АктивироватьИУстановитьСертификатПослеПроверкиПароля", ЭтотОбъект, ВходящийКонтекст);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПараметрыОперации	= Новый Структура();
		ПараметрыОперации.Вставить("Принудительно", Истина);
		ПараметрыОперации.Вставить("ОжидатьВыполнения", Истина);
		ПараметрыОперации.Вставить("ПояснениеОперации", НСтр("ru = 'Авторизуйтесь на сервере DSS с помощью пароля, полученного ранее.'"));
		СервисКриптографииDSSКлиент.ПроверкаАутентификацииПользователя(ОповещениеСледующее, НастройкиПользователя, ПараметрыОперации);
		
	Иначе
		РезультатВыполнения = ОтветСервисаПоУмолчанию(Ложь);
		ПолучитьОписаниеОшибки(РезультатВыполнения,
							ВходящийКонтекст.ТипОшибки,
							НСтр("ru = 'Ошибка при активировании учетной записи'"));
		АктивироватьИУстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст); 
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры АктивироватьИУстановитьСертификат.
Процедура АктивироватьИУстановитьСертификатПослеПроверкиПароля(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	Если РезультатВыполнения.Выполнено Тогда
		АктивироватьИУстановитьСертификатПроверитьСертификат(РезультатВыполнения, ВходящийКонтекст);
	Иначе
		РезультатВыполнения = ОтветСервисаПоУмолчанию(Ложь);
		ПолучитьОписаниеОшибки(РезультатВыполнения,
							ВходящийКонтекст.ТипОшибки,
							НСтр("ru = 'Неудачная авторизация с новым паролем'"));
		АктивироватьИУстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст); 
	КонецЕсли;

КонецПроцедуры

// Продолжение процедуры АктивироватьИУстановитьСертификат.
Процедура АктивироватьИУстановитьСертификатПроверитьСертификат(РезультатВыполнения, ВходящийКонтекст)

	НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
    ОтпечатокСертификата = ВходящийКонтекст.ОтпечатокСертификата;
    ДанныеСертификата = ВходящийКонтекст.ДанныеСертификата;
    ПараметрыОперации = ВходящийКонтекст.ПараметрыОперации;
	УстановитьСертификат = ВходящийКонтекст.УстановитьСертификат;
	
	Если РезультатВыполнения.Выполнено Тогда
		Если УстановитьСертификат Тогда
			УстановитьСертификат = НЕ АктивироватьИУстановитьСертификатНайтиСертификат(НастройкиПользователя, ОтпечатокСертификата);
		КонецЕсли;
		
		Если УстановитьСертификат Тогда
			ОбъектОповещения = Новый ОписаниеОповещения("АктивироватьИУстановитьСертификатПослеУстановкиСертификата", ЭтотОбъект, ВходящийКонтекст);
			ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
			СервисКриптографииDSSКлиент.УстановитьСертификат(ОповещениеСледующее, НастройкиПользователя, ДанныеСертификата, ПараметрыОперации);
		Иначе
			АктивироватьИУстановитьСертификатПолучитьРасписку(РезультатВыполнения, ВходящийКонтекст);
		КонецЕсли;
		
	Иначе
		РезультатВыполнения = ОтветСервисаПоУмолчанию(Ложь);
		ПолучитьОписаниеОшибки(РезультатВыполнения,
							ВходящийКонтекст.ТипОшибки,
							НСтр("ru = 'Обновление списка сертификатов из хранилища сертификатов сервера DSS'", КодЯзыка()));
		АктивироватьИУстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст); 
		
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры АктивироватьИУстановитьСертификат.
Функция АктивироватьИУстановитьСертификатНайтиСертификат(НастройкиПользователя, ОтпечатокСертификата)
	
	НашлиСертификат = СервисКриптографииDSSКлиентСервер.НайтиСертификат(НастройкиПользователя, ОтпечатокСертификата);
	Результат = ЗначениеЗаполнено(НашлиСертификат.Отпечаток);
	
	Возврат Результат;
	
КонецФункции

// Продолжение процедуры АктивироватьИУстановитьСертификат.
Процедура АктивироватьИУстановитьСертификатПослеУстановкиСертификата(ОтветСервиса, ВходящийКонтекст) Экспорт

	Если НЕ ОтветСервиса.Выполнено Тогда
		РезультатВыполнения = ОтветСервисаПоУмолчанию(Ложь);
		ПолучитьОписаниеОшибки(РезультатВыполнения,
							ВходящийКонтекст.ТипОшибки,
							ОтветСервиса.Ошибка);
		АктивироватьИУстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст);
	Иначе
		АктивироватьИУстановитьСертификатПолучитьРасписку(РезультатВыполнения, ВходящийКонтекст);
	КонецЕсли;
	
КонецПроцедуры

Процедура АктивироватьИУстановитьСертификатПолучитьРасписку(РезультатВыполнения, ВходящийКонтекст)
	
	Если ВходящийКонтекст.ДействиеПолучитьРасписку Тогда
		АктивироватьИУстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст); 
	Иначе
		АктивироватьИУстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст); 
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры АктивироватьИУстановитьСертификат.
Процедура АктивироватьИУстановитьСертификатРезультат(РезультатВыполнения, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВыполнения);
	
КонецПроцедуры

#КонецОбласти

#Область ВосстановитьУчетнуюЗапись

// Запускает цикл восстановления учетной записи облачной подписи
//
// Шаги цикла:
// 1. подготовка параметров цикла
// 2. авторизация по логину
// 3. запуск процесса подтверждения операции (контрольная подпись)
// 4. создание элемента справочника
// 5. возврат результат операции.
//
Процедура ВосстановитьУчетнуюЗапись(ОповещениеОЗавершении, ДанныеСервера, Логин, Пароль, ПараметрыОперации) Экспорт
	
	НастройкиПользователя = СервисКриптографииDSSСлужебныйВызовСервера.ДополнитьНастройкиПользователя(ДанныеСервера, Логин);
	НастройкиПользователя.ПервичнаяАутентификация = ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_УчетныеДанные");
	Если ЗначениеЗаполнено(Пароль) Тогда
		НастройкиПользователя.Пароль = Пароль;
	КонецЕсли;
	
	ПараметрыЦикла = Новый Структура;
	ПараметрыЦикла.Вставить("ВидОперации", НСтр("ru = 'Восстановление учетной записи'", КодЯзыка()));
	ПараметрыЦикла.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("ДанныеСервера", ДанныеСервера);
	ПараметрыЦикла.Вставить("Логин", ОповещениеОЗавершении);
	ПараметрыЦикла.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыЦикла.Вставить("ПараметрыОперации", ПроверитьПараметрыОперации(ПараметрыОперации));
	ПараметрыЦикла.Вставить("СпособПодтверждения", СвойствоСтруктуры(ПараметрыОперации, "СпособПодтверждения"));
	
	ОбъектОповещения	= Новый ОписаниеОповещения("ВосстановитьУчетнуюЗаписьПослеПроверки", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	ПроверкаАутентификацииПользователя(ОповещениеСледующее, ПараметрыЦикла);
		
КонецПроцедуры

// Продолжение процедуры ВосстановитьУчетнуюЗапись.
Процедура ВосстановитьУчетнуюЗаписьПослеПроверки(РезультатВыполнения, ВходящийКонтекст) Экспорт 
	
	НастройкиПользователя = ВходящийКонтекст.НастройкиПользователя;
	СпособПодтверждения = ВходящийКонтекст.СпособПодтверждения;
	ПараметрыОперации = ВходящийКонтекст.ПараметрыОперации;
	
	Если РезультатВыполнения.Выполнено Тогда
		ОбъектОповещения	= Новый ОписаниеОповещения("ВосстановитьУчетнуюЗаписьПослеПодтверждения", ЭтотОбъект);
		ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ВходящийКонтекст);
		ПодтверждениеПроизвольнойОперации(НастройкиПользователя, 
							ОповещениеСледующее, 
							НСтр("ru = 'Подтвердите создание учетной записи'"),
							СпособПодтверждения,
							ПараметрыОперации);
	Иначе
		ВосстановитьУчетнуюЗаписьРезультат(РезультатВыполнения, ВходящийКонтекст);
		
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры ВосстановитьУчетнуюЗапись.
Процедура ВосстановитьУчетнуюЗаписьПослеПодтверждения(РезультатВыполнения, ВходящийКонтекст) Экспорт
	
	ДанныеСервера = ВходящийКонтекст.ДанныеСервера;
	Логин = ВходящийКонтекст.Логин;
	
	Если РезультатВыполнения.Выполнено Тогда
		НоваяУчетнаяЗапись = СервисКриптографииDSSСлужебныйВызовСервера.СоздатьУчетнуюЗаписьОблачнойПодписи(ДанныеСервера, Логин);
		Если ЗначениеЗаполнено(НоваяУчетнаяЗапись) Тогда
			РезультатОперации = ОтветСервисаПоУмолчанию();
			РезультатОперации.Вставить("Результат", НоваяУчетнаяЗапись);
		Иначе
			РезультатОперации = ОтветСервисаПоУмолчанию(Ложь);
			ЗаголовокОшибки = НСтр("ru = 'Не удалось создать учетную запись DSS'");
			ПолучитьОписаниеОшибки(РезультатОперации,
								"СозданиеУчетнойЗаписи",
								ЗаголовокОшибки);
			
		КонецЕсли;	
	Иначе
		РезультатОперации = РезультатВыполнения; 
	КонецЕсли;
	
	ВосстановитьУчетнуюЗаписьРезультат(РезультатОперации, ВходящийКонтекст);
	
КонецПроцедуры
		
// Продолжение процедуры ВосстановитьУчетнуюЗапись.
Процедура ВосстановитьУчетнуюЗаписьРезультат(РезультатВыполнения, ВходящийКонтекст)
	
	ВернутьРезультатВызова(ВходящийКонтекст, РезультатВыполнения);

КонецПроцедуры

#КонецОбласти

#Область ПрочиеФункции

// Функция-обертка используется для централизованного управление языком при формировании сообщений пользователю
//
// Возвращаемое значение:
//  Строка - текстовый код языка (альфа2)
//
Функция КодЯзыка() Экспорт
	
	Возврат ОбщегоНазначенияКлиент.КодОсновногоЯзыка();
	
КонецФункции

// Функция-обертка для разбора веб-адреса сервисов
//
// Параметры:
//  АдресURI - Строка
// 
// Возвращаемое значение:
//   см. ОбщегоНазначенияКлиентСервер.СтруктураURI
//
Функция СтруктураВебАдреса(АдресURI) Экспорт
	
	Возврат ОбщегоНазначенияКлиентСервер.СтруктураURI(АдресURI);
	
КонецФункции

// Функция-обертка для разбора полей структуры
//
// Параметры:
//  Структура - Структура
//  Ключ - Строка
//  ЗначениеПоУмолчанию - Произвольный
// 
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ПолучитьПолеСтруктуры
//
Функция СвойствоСтруктуры(Структура, Ключ, ЗначениеПоУмолчанию = Неопределено) Экспорт
	
	Возврат СервисКриптографииDSSКлиентСервер.ПолучитьПолеСтруктуры(Структура, Ключ, ЗначениеПоУмолчанию);
		
КонецФункции	

// Функция-обертка для получения даты и времени сеанса
//
// Возвращаемое значение:
//  Дата
//
Функция ДатаСеанса() Экспорт
	
	Возврат ОбщегоНазначенияКлиент.ДатаСеанса();
	
КонецФункции

// Процедура для оценки производительности работы с облачной подписью
// 
// Параметры:
//  ВходящийКонтекст 	- Структура - должно содержать поле "ВидОперации"
//  ПолеСтруктуры		- Строка
//  ШагОперации			- Строка
//
Процедура НачатьЗамерВремени(ВходящийКонтекст, ПолеСтруктуры = "ВидОперации", ШагОперации = "") Экспорт
	
	// СтандартныеПодсистемы.ОценкаПроизводительности
	
	Если ОбщегоНазначенияКлиент.ПодсистемаСуществует("СтандартныеПодсистемы.ОценкаПроизводительности") Тогда
		
		ВидОперации = СвойствоСтруктуры(ВходящийКонтекст, ПолеСтруктуры);
		КлючеваяОперация = "ВыполнениеОперацииОблачнойПодписи";
		
		Если ЗначениеЗаполнено(ВидОперации) Тогда
			КлючеваяОперация = КлючеваяОперация + " - " + ВидОперации;
		КонецЕсли;
		
		Если ЗначениеЗаполнено(ШагОперации) Тогда
			КлючеваяОперация = КлючеваяОперация + " (" + ШагОперации + ")";
		КонецЕсли;
		
		МодульОценкаПроизводительностиКлиент = ОбщегоНазначенияКлиент.ОбщийМодуль("ОценкаПроизводительностиКлиент");
		ИдентификаторЗамера = МодульОценкаПроизводительностиКлиент.ЗамерВремени(КлючеваяОперация);
		ВходящийКонтекст.Вставить("ИдентификаторЗамера", ИдентификаторЗамера);
			
	КонецЕсли;
	
	// Конец СтандартныеПодсистемы.ОценкаПроизводительности
	
КонецПроцедуры

// Процедура для оценки производительности работы с облачной подписью
// 
// Параметры:
//  ВходящийКонтекст - Структура - должно содержать поле "ВидОперации"
//
Процедура ЗакончитьЗамерВремени(ВходящийКонтекст) Экспорт
	
	// СтандартныеПодсистемы.ОценкаПроизводительности
	Если ВходящийКонтекст = Неопределено Тогда
		Возврат;
	КонецЕсли;	
	
	Если ОбщегоНазначенияКлиент.ПодсистемаСуществует("СтандартныеПодсистемы.ОценкаПроизводительности") Тогда
		
		Если ВходящийКонтекст = "Ошибка" Тогда
			МодульОценкаПроизводительностиКлиент = ОбщегоНазначенияКлиент.ОбщийМодуль("ОценкаПроизводительностиКлиент");
			
		Иначе
			ИдентификаторЗамера = СвойствоСтруктуры(ВходящийКонтекст, "ИдентификаторЗамера");
			
			Если ЗначениеЗаполнено(ИдентификаторЗамера) Тогда
				ВходящийКонтекст.Удалить("ИдентификаторЗамера");
				МодульОценкаПроизводительностиКлиент = ОбщегоНазначенияКлиент.ОбщийМодуль("ОценкаПроизводительностиКлиент");
				МодульОценкаПроизводительностиКлиент.ЗавершитьЗамерВремени(ИдентификаторЗамера);
			КонецЕсли;
			
		КонецЕсли;
		
	КонецЕсли;
	
	// Конец СтандартныеПодсистемы.ОценкаПроизводительности
	
КонецПроцедуры

// Процедура для открытия навигационной ссылки в браузере.
//
// Параметры:
//  НавигационнаяСсылка - Строка
//  ТипОбозревателя		- Строка - предпочтительный обозреватель для открытия, нужно передать имя
//	
Процедура ОткрытьВБраузере(НавигационнаяСсылка, ТипОбозревателя) Экспорт
	
	БраузерКлиента = ИмяБраузера();
	ЛюбойБраузер = Истина;
	
	Если ТипОбозревателя = "MSIE" Тогда
		ЛюбойБраузер = НЕ ОбщегоНазначенияКлиент.ЭтоWindowsКлиент();
	КонецЕсли;
	
	Если НЕ ЛюбойБраузер Тогда
		Если ЭтоВебКлиент() И БраузерКлиента = "MSIE" Тогда
			ЛюбойБраузер = Истина;
		КонецЕсли;	
	КонецЕсли;
	
	Если ЛюбойБраузер Тогда
		ФайловаяСистемаКлиент.ОткрытьНавигационнуюСсылку(НавигационнаяСсылка);
	Иначе 	
		ФайловаяСистемаКлиент.ЗапуститьПрограмму("rundll32 shell32.dll, ShellExec_RunDLL iexplore " + НавигационнаяСсылка);
	КонецЕсли;
	
КонецПроцедуры
	
#КонецОбласти

#Область СлужебныеДляОткрытияФормСервиса

// Только для внутреннего использования.
// Проверяет передаваемые параметры с клиента на сервер, на допустимые типы.
//
// Параметры:
//  ПараметрыФормы - Структура
//
// Возвращаемое значение:
//  Структура
//	
Функция ПодготовитьПараметрыФормы(ПараметрыФормы) Экспорт
	
	Результат = ПараметрыФормы;
	
	Если ПараметрыФормы <> Неопределено Тогда
		Для каждого СтрокаКлюча Из Результат Цикл
			
			Если ТипЗнч(СтрокаКлюча.Значение) = Тип("ФормаКлиентскогоПриложения") 
				ИЛИ ТипЗнч(СтрокаКлюча.Значение) = Тип("ОписаниеОповещения") Тогда
				Результат.Вставить(СтрокаКлюча.Ключ, Неопределено);
			ИначеЕсли ТипЗнч(СтрокаКлюча.Значение) = Тип("Структура") Тогда
				Результат.Вставить(СтрокаКлюча.Ключ, ПодготовитьПараметрыФормы(СтрокаКлюча.Значение));
			КонецЕсли;
			
		КонецЦикла;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Только для внутреннего использования.
Функция ОткрытьФормуВзаимодействия(ИдентификаторФормы, ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении, Знач ТолькоПроверить = Ложь)
	
	Результат = Ложь;
	
	НоваяФорма = СвойствоСтруктуры(ПараметрыОперации, "Форма" + ИдентификаторФормы);
	
	Если ЗначениеЗаполнено(НоваяФорма) Тогда
		Результат = Истина;
		ПодготовленныеПараметры = ПроверитьПараметрыОперации(ПараметрыФормы);
		ПодготовленныеПараметры.Вставить("ПараметрыОперации", ПодготовитьПараметрыФормы(ПараметрыОперации));
		ПолноеИмяФормы = НоваяФорма;
		ТолькоПроверить = Ложь;
	Иначе
		ПодготовленныеПараметры = ПодготовитьПараметрыФормы(ПараметрыФормы);
		ПолноеИмяФормы = "Обработка.УправлениеПодключениемDSS.Форма." + ИдентификаторФормы;
	КонецЕсли;
	
	РежимОткрытияОкна = СвойствоСтруктуры(ПараметрыОперации, "РежимОткрытияОкна");
	
	Если НЕ ТолькоПроверить Тогда
		ОткрытьФорму(ПолноеИмяФормы, ПодготовленныеПараметры, , , , , ОбъектОповещенияОбработкиФормы(ОповещениеОЗавершении), РежимОткрытияОкна);
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Только для внутреннего использования.
Процедура ОткрытьФормуВводПароля(НастройкиПользователя,
								ОповещениеОЗавершении,
								РежимВвода,
								ВозможноСохранять = Неопределено,
								ПараметрыОперации = Неопределено)
	
	ПараметрыФормы 			= Новый Структура;
	ПараметрыФормы.Вставить("РежимВвода", РежимВвода);
	ПараметрыФормы.Вставить("ВозможноСохранять", ВозможноСохранять);
	ПараметрыФормы.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыФормы.Вставить("ПояснениеОперации", СвойствоСтруктуры(ПараметрыОперации, "ПояснениеОперации"));
	
	ОткрытьФормуВзаимодействия("ВводПароля", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении);
	
КонецПроцедуры	

// Только для внутреннего использования.
Процедура ОткрытьФормуВводПинКода(НастройкиПользователя, ОповещениеОЗавершении, Сертификат, ПараметрыОперации)
	
	ПараметрыФормы 			= Новый Структура;
	ПараметрыФормы.Вставить("Сертификат", Сертификат);
	ПараметрыФормы.Вставить("НастройкиПользователя", НастройкиПользователя);
	
	ОткрытьФормуВзаимодействия("ВводПинКода", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении);
	
КонецПроцедуры	

// Только для внутреннего использования.
Процедура ОткрытьФормуВебАутентификации(НастройкиПользователя, ОповещениеОЗавершении, ПараметрыОперации)
	
	ПараметрыФормы 			= Новый Структура;
	ПараметрыФормы.Вставить("НастройкиПользователя", НастройкиПользователя);
	
	ОткрытьФормуВзаимодействия("ВебАутентификация", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОткрытьФормуЗапросаНаСертификат(НастройкиПользователя, ОповещениеОЗавершении, ПоляЗапроса, ПараметрыОперации)
	
	ПараметрыФормы 			= Новый Структура;
	ПараметрыФормы.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыФормы.Вставить("ПоляЗапроса", ПоляЗапроса);
	
	ОткрытьФормуВзаимодействия("НовыйЗапросНаСертификат", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОткрытьФормуСменыПароля(НастройкиПользователя, ОповещениеОЗавершении, РежимФормы = "Смена", Обязательно = Ложь, ПараметрыОперации = Неопределено)
	
	ПараметрыФормы 			= Новый Структура;
	ПараметрыФормы.Вставить("РежимФормы", РежимФормы);
	ПараметрыФормы.Вставить("Обязательно", Обязательно);
	ПараметрыФормы.Вставить("Обязательно", Обязательно);
	ПараметрыФормы.Вставить("ПояснениеОперации", СвойствоСтруктуры(ПараметрыОперации, "ПояснениеОперации"));
	
	ОткрытьФормуВзаимодействия("СменаПинКода", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОткрытьФормуВыбораСертификата(НастройкиПользователя, 
				ОповещениеОЗавершении, 
				РежимВыбора,
				ПолноеОписание = Ложь,
				МассивВыбора = Неопределено,
				ПараметрыОперации = Неопределено)
	
	ПараметрыФормы 			= Новый Структура;
	ПараметрыФормы.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыФормы.Вставить("ВыборИзСписка", Истина);
	ПараметрыФормы.Вставить("ПолноеОписание", ПолноеОписание);
	ПараметрыФормы.Вставить("РежимВыбора", РежимВыбора);
	ПараметрыФормы.Вставить("МассивВыбора", МассивВыбора);
	
	ОткрытьФормуВзаимодействия("СписокСертификатов", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОткрытьФормуСостоянияУчетнойЗаписи(НастройкиПользователя, ОповещениеОЗавершении, ПараметрыОперации) 
	
	ПараметрыФормы 			= Новый Структура;
	ПараметрыФормы.Вставить("Отбор", Новый Структура("НастройкиПользователя", НастройкиПользователя));
	ПараметрыФормы.Вставить("СформироватьПриОткрытии", Истина);
	
	Если НЕ ОткрытьФормуВзаимодействия("СостояниеУчетнойЗаписиDSS", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении, Истина) Тогда
		ОткрытьФорму("Отчет.СостояниеУчетнойЗаписиDSS.Форма", ПараметрыФормы, ПараметрыОперации, ОбъектОповещенияОбработкиФормы(ОповещениеОЗавершении));
	КонецЕсли;
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОткрытьФормуСертификата(НастройкиПользователя, 
									ОповещениеОЗавершении, 
									ПараметрыФормы, 
									ФормаВладелец = Неопределено, 
									ПараметрыОперации = Неопределено)
	
	ПоказатьСведениеСервиса = СвойствоСтруктуры(ПараметрыОперации, "ПоказатьСведениеСервиса", Ложь);
	
	Если ПоказатьСведениеСервиса Тогда
		ИмяФормы = "Обработка.УправлениеПодключениемDSS.Форма.СвойствоСертификата";
	Иначе	
		ИмяФормы = "ОбщаяФорма.Сертификат";
	КонецЕсли;	
	
	Если НЕ ОткрытьФормуВзаимодействия("ФормаСвойствоСертификата", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении, Истина) Тогда
		Если ФормаВладелец = Неопределено Тогда
			ОткрытьФорму(ИмяФормы, ПараметрыФормы, , , , , ОбъектОповещенияОбработкиФормы(ОповещениеОЗавершении));
		Иначе
			ОткрытьФорму(ИмяФормы, ПараметрыФормы, 
				ФормаВладелец, , , , ОбъектОповещенияОбработкиФормы(ОповещениеОЗавершении), РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
		КонецЕсли;
	КонецЕсли;		
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОткрытьФормуВыбораУчетнойЗаписи(ОповещениеОЗавершении, ПараметрыОперации)
	
	ПараметрыФормы = Новый Структура;
	ПараметрыФормы.Вставить("ПараметрыОперации", ПараметрыОперации);
	
	ОткрытьФормуВзаимодействия("ВыборТекущейУчетнойЗаписи", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОткрытьФормуСведенийУчетнойЗаписи(ОповещениеОЗавершении, СсылкаУчетнойЗаписи, ПараметрыОперации)
	
	Если ПараметрыОперации = Неопределено Тогда
		ПараметрыФормы = Новый Структура;
	Иначе
		ПараметрыФормы = ПараметрыОперации;
	КонецЕсли;
	
	Если ЗначениеЗаполнено(СсылкаУчетнойЗаписи) Тогда
		ПараметрыФормы.Вставить("Ключ", СсылкаУчетнойЗаписи);
	КонецЕсли;	
	
	ОткрытьФормуВзаимодействия("ФормаУчетнойЗаписи", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОткрытьФормуСведенийСервера(ОповещениеОЗавершении, СсылкаСервера, ПараметрыОперации)
	
	Если ПараметрыОперации = Неопределено Тогда
		ПараметрыФормы = Новый Структура;
	Иначе
		ПараметрыФормы = ПараметрыОперации;
	КонецЕсли;
	
	Если ЗначениеЗаполнено(СсылкаСервера) Тогда
		ПараметрыФормы.Вставить("Ключ", СсылкаСервера);
	КонецЕсли;	
	
	ОткрытьФормуВзаимодействия("ФормаЭкземпляраСервераDSS", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОткрытьФормуВыбораЭкземпляраСервера(ОповещениеОЗавершении, ПараметрыОперации)
	
	Если ПараметрыОперации = Неопределено Тогда
		ПараметрыФормы = Новый Структура;
	Иначе
		ПараметрыФормы = ПараметрыОперации;
	КонецЕсли;
	
	ОткрытьФормуВзаимодействия("ВыборЭкземпляровСервераDSS", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОткрытьФормуПроверкиРаботоспособности(НастройкиПользователя, 
												ОповещениеОЗавершении = Неопределено, 
												СписокОпераций = Неопределено, 
												ПараметрыОперации = Неопределено)
	
	ПараметрыФормы = Новый Структура();
	ПараметрыФормы.Вставить("НастройкиПользователя", НастройкиПользователя);
	ПараметрыФормы.Вставить("СписокОпераций", СписокОпераций);
	
	ОткрытьФормуВзаимодействия("ПроверкаСервиса", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОткрытьФормуВыбораНастроекСервиса(ОписаниеСервиса, 
											ОповещениеОЗавершении = Неопределено, 
											ПараметрыОперации = Неопределено)
	
	ПараметрыФормы = Новый Структура("ОписаниеСервисаОбнаружения", ОписаниеСервиса);
	ОткрытьФормуВзаимодействия("ВыборСервисаИзОписания", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОткрытьФормуВыборПрограммы(ОповещениеОЗавершении = Неопределено, ПараметрыОперации = Неопределено)
	
	ПараметрыФормы = Новый Структура();
	ОткрытьФормуВзаимодействия("ВыборПрограммы", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОткрытьФормуЗаявленияНаИзменение(ОповещениеОЗавершении, ПараметрыФормы, ПараметрыОперации = Неопределено)
	
	ОткрытьФормуВзаимодействия("ЗаявлениеНаИзменениеРеквизитовПодключения", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОткрытьФормуПодбораУчетныхЗаписей(ОповещениеОЗавершении, ПараметрыФормы, ПараметрыОперации = Неопределено)
	
	ОткрытьФормуВзаимодействия("ПодборУчетнойЗаписи", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОткрытьФормуПодтверждения(ОповещениеОЗавершении, ПараметрыФормы, ПараметрыОперации = Неопределено)
	
	ОткрытьФормуВзаимодействия("ПодтверждениеПользователя", ПараметрыФормы, ПараметрыОперации, ОповещениеОЗавершении);

КонецПроцедуры

// Только для внутреннего использования.
Процедура ОтобразитьОшибкуПользователю(ОповещениеСледующее, 
										ТекстОшибки = "", 
										ЭтоКодОшибки = Ложь, 
										ПараметрыОперации = Неопределено)
	
	СервисКриптографииDSSСлужебныйВызовСервера.НачальныеНастройкиФормы("ВывестиИнформацию");
	
	ПараметрыФормы 			= Новый Структура;
	ПараметрыФормы.Вставить("ТекстСообщения", ТекстОшибки);
	ПараметрыФормы.Вставить("ПараметрыОперации", ПараметрыОперации);
	ПараметрыФормы.Вставить("ЭтоКодОшибки", ЭтоКодОшибки);
	ПараметрыФормы.Вставить("РежимОтображения", "Ошибка");
	
	ОткрытьФормуВзаимодействия("ВывестиИнформацию", ПараметрыФормы, ПараметрыОперации, ОповещениеСледующее);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОтобразитьИнформациюПользователю(ОповещениеСледующее, 
										ТекстСообщения, 
										ТаймАут = Неопределено, 
										Заголовок = "", 
										ПараметрыОперации = Неопределено)
	
	СервисКриптографииDSSСлужебныйВызовСервера.НачальныеНастройкиФормы("ВывестиИнформацию");
	
	ПараметрыФормы 			= Новый Структура;
	ПараметрыФормы.Вставить("ТекстСообщения", ТекстСообщения);
	ПараметрыФормы.Вставить("ТаймАут", ТаймАут);
	ПараметрыФормы.Вставить("Заголовок", Заголовок);
	ПараметрыФормы.Вставить("РежимОтображения", "Информация");
	
	ОткрытьФормуВзаимодействия("ВывестиИнформацию", ПараметрыФормы, ПараметрыОперации, ОповещениеСледующее);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ОтобразитьВопросПользователю(ОповещениеСледующее, 
										ТекстСообщения,
										СписокКоманд,
										ТаймАут = Неопределено, 
										Заголовок = "",
										ПараметрыОперации = Неопределено)
	
	СервисКриптографииDSSСлужебныйВызовСервера.НачальныеНастройкиФормы("ВывестиИнформацию");
	
	ПараметрыФормы 			= Новый Структура;
	ПараметрыФормы.Вставить("ТекстСообщения", ТекстСообщения);
	ПараметрыФормы.Вставить("ТаймАут", ТаймАут);
	ПараметрыФормы.Вставить("Заголовок", Заголовок);
	ПараметрыФормы.Вставить("РежимОтображения", "Вопрос");
	ПараметрыФормы.Вставить("СписокКоманд", СписокКоманд);
	
	ОткрытьФормуВзаимодействия("ВывестиИнформацию", ПараметрыФормы, ПараметрыОперации, ОповещениеСледующее);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ПослеЗакрытияФормы(РезультатВыбора, ПараметрыЦикла) Экспорт
	
	Если РезультатВыбора = Неопределено Тогда
		ЗавершениеРаботы = СвойствоСтруктуры(ПараметрыЦикла, "ЗавершениеРаботы", Ложь);
		Если ЗавершениеРаботы Тогда
			РезультатВыбора = ОтветСервисаПоУмолчанию(Ложь, "ЗавершениеРаботы");
		Иначе
			РезультатВыбора = ОтветСервисаПоУмолчанию(Ложь, "ОтказПользователя");
		КонецЕсли;
	КонецЕсли;
	
	ОповещениеСледующее = СвойствоСтруктуры(ПараметрыЦикла, "ОповещениеСледующее");
	
	Если ОповещениеСледующее <> Неопределено Тогда
		ВыполнитьОбработкуОповещения(ОповещениеСледующее, РезультатВыбора);
	КонецЕсли;
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ПриОткрытииФормы(ЭтотОбъект, ПрограммноеЗакрытие) Экспорт
	
	ПрограммноеЗакрытие = Ложь;
	
КонецПроцедуры

// Только для внутреннего использования.
//
// Параметры:
//  ФормаВладелец   				- ФормаКлиентскогоПриложения - содержит реквизиты:
//    * ОписаниеОповещенияОЗакрытии	- ОписаниеОповещения
//  Отказ							- Булево
//  ПрограммноеЗакрытие				- Булево
//  ЗавершениеРаботы				- Булево
// 
// Возвращаемое значение:
//  Булево
//
Функция ПередЗакрытиемФормы(ФормаВладелец, Отказ, ПрограммноеЗакрытие, ЗавершениеРаботы) Экспорт
	
	ЭтоВебКлиент = ЭтоВебКлиент();
	ЗакрытьФорму = Ложь;
	
	Если ЗавершениеРаботы ИЛИ ЭтоВебКлиент ИЛИ ПрограммноеЗакрытие Тогда
		ЗакрытьФорму = Истина;
	КонецЕсли;
	
	Если ФормаВладелец.ОписаниеОповещенияОЗакрытии = Неопределено Тогда
		ЗакрытьФорму = Истина;
	ИначеЕсли ФормаВладелец.ОписаниеОповещенияОЗакрытии.ДополнительныеПараметры <> Неопределено Тогда
		ФормаВладелец.ОписаниеОповещенияОЗакрытии.ДополнительныеПараметры.Вставить("ЗавершениеРаботы", ЗавершениеРаботы);
	КонецЕсли;	
	
	Если НЕ ЗакрытьФорму Тогда
		ПрограммноеЗакрытие = Истина;
		Отказ = Истина;
	КонецЕсли;
	
	Возврат НЕ ЗакрытьФорму;
	
КонецФункции

Функция ОбъектОповещенияОбработкиФормы(ОповещениеОЗавершении) Экспорт
	
	ПараметрыЦикла = Новый Структура;
	ПараметрыЦикла.Вставить("ЗавершениеРаботы", Ложь);
	ПараметрыЦикла.Вставить("ОповещениеСледующее", ОповещениеОЗавершении);
	
	ОбъектОповещения = Новый ОписаниеОповещения("ПослеЗакрытияФормы", ЭтотОбъект);
	ОповещениеСледующее = ОбработчикОповещения(ОбъектОповещения, ПараметрыЦикла);
	
	Возврат ОповещениеСледующее;
	
КонецФункции

#КонецОбласти

#Область ВспомогательныеПроцедурыИФункции

// Функция-обертка. см. СервисКриптографииDSSСлужебныйВызовСервера.СохранитьЗакрытыеДанные
Процедура СохранитьЗакрытыеДанные(ИдентификаторДанных, Значение, ИмяЗначения = "")
	
	СервисКриптографииDSSСлужебныйВызовСервера.СохранитьЗакрытыеДанные(ИдентификаторДанных, Значение, ИмяЗначения);
	Оповестить("СервисКриптографииDSS_ЗаписьЗащищенныхДанных");
	
КонецПроцедуры

// Служебная для вызова обработки оповещения вызывающей стороны.
//
// Параметры:
//  ВходящийКонтекст 			- Структура:
//    * ОповещениеОЗавершении	- ОписаниеОповещения
//    							- Неопределено
//    * ПараметрыОперации		- Структура - необязательный.
//  РезультатВызова				- см. ОтветСервисаПоУмолчанию
//  ПодготовленныйРезультат		- Неопределено
//                         		- Структура
//
Процедура ВернутьРезультатВызова(ВходящийКонтекст, РезультатВызова, ПодготовленныйРезультат = Неопределено)
	
	Если ПодготовленныйРезультат = Неопределено Тогда
		ПодготовленныйРезультат = РезультатВызова;
	КонецЕсли;

	ОповещениеОЗавершении = ВходящийКонтекст.ОповещениеОЗавершении;
	
	Если ОповещениеОЗавершении <> Неопределено 
		И ТипЗнч(ОповещениеОЗавершении.ДополнительныеПараметры) = Тип("Структура") Тогда
		Если РезультатВызова.МаркерОбновлен Тогда
			ОповещениеОЗавершении.ДополнительныеПараметры.Вставить("НастройкиПользователя", РезультатВызова.НастройкиПользователя);
		КонецЕсли;	
	КонецЕсли;	
	
	ПоказатьОшибку = Ложь;
	Если ОповещениеОЗавершении = Неопределено Тогда
		ПоказатьОшибку = Истина;
	ИначеЕсли ВходящийКонтекст.Свойство("ПараметрыОперации") Тогда
		Если НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст) Тогда
			ПоказатьОшибку = Ложь;
		Иначе	
			ПоказатьОшибку = СвойствоСтруктуры(ВходящийКонтекст.ПараметрыОперации, "ОтобразитьОшибку", Ложь);
		КонецЕсли;
	КонецЕсли;	
	
	Если ПоказатьОшибку 
		И НЕ РезультатВызова.Выполнено 
		И ЗначениеЗаполнено(РезультатВызова.Ошибка) 
		И НЕ СервисКриптографииDSSКлиентСервер.ЭтоОшибкаОтказа(РезультатВызова.Ошибка) Тогда
		ВывестиОшибку(ОповещениеОЗавершении, РезультатВызова.Ошибка, , ПодготовленныйРезультат);
	ИначеЕсли ОповещениеОЗавершении <> Неопределено Тогда
		ВыполнитьОбработкуОповещения(ОповещениеОЗавершении, ПодготовленныйРезультат);
	КонецЕсли;
	
КонецПроцедуры	

// Проверяет и подготавливает параметры операции
//
Функция ПроверитьПараметрыОперации(ПараметрыОперации = Неопределено)
	
	Результат = Новый Структура;
	
	Если ТипЗнч(ПараметрыОперации) = Тип("Структура") Тогда
		Результат = ОбщегоНазначенияКлиент.СкопироватьРекурсивно(ПараметрыОперации);
	КонецЕсли;
	
	Возврат ПодготовитьПараметрыФормы(Результат);
	
КонецФункции

// Функция-обертка, служит для формирования нового объекта "ОписаниеОповещения" со встроенной обработкой критических ошибок
//
// Параметры:
//  ДанныеОбработчика 	- Строка
//                    	- ОписаниеОповещения
//  ПараметрыВызова 	- Произвольный
//
// Возвращаемое значение:
//  ОписаниеОповещения
//
Функция ОбработчикОповещения(ДанныеОбработчика, ПараметрыВызова = Неопределено)
	
	Если ТипЗнч(ДанныеОбработчика) = Тип("Строка") Тогда
		Результат = Новый ОписаниеОповещения(ДанныеОбработчика, 
						ЭтотОбъект, 
						ПараметрыВызова, 
						"ОшибкаПриРаботеСервиса", 
						ЭтотОбъект);
	Иначе
		Результат = Новый ОписаниеОповещения(ДанныеОбработчика.ИмяПроцедуры, 
						ЭтотОбъект, 
						ПараметрыВызова, 
						"ОшибкаПриРаботеСервиса", 
						ЭтотОбъект);
	КонецЕсли;					
					
	Возврат Результат;
	
КонецФункции

// Служебная процедура проверки обновления маркера доступа в результате вызова сервиса
//
Процедура ПроверитьТокенНаОбновление(РезультатВызова, НастройкиПользователя, ОбновитьВерсию = Ложь)
	
	НовыеНастройки = Неопределено;
	
	Если РезультатВызова.МаркерОбновлен Тогда
		НовыеНастройки = СвойствоСтруктуры(РезультатВызова, "НастройкиПользователя");
	ИначеЕсли ОбновитьВерсию Тогда
		НовыеНастройки = СвойствоСтруктуры(РезультатВызова, "НастройкиПользователя");
	КонецЕсли;
	
	Если НовыеНастройки <> Неопределено Тогда
		КлючТекущий = СервисКриптографииDSSКлиентСервер.КлючНастроекПользователя(НастройкиПользователя);
		КлючНовый = СервисКриптографииDSSКлиентСервер.КлючНастроекПользователя(НовыеНастройки);
		Если КлючТекущий = КлючНовый Тогда
			Если НастройкиПользователя.ВерсияНастройки > НовыеНастройки.ВерсияНастройки Тогда
				СервисКриптографииDSSСлужебныйВызовСервера.ОбновитьНастройкиПользователя(НастройкиПользователя, НовыеНастройки);
			КонецЕсли;
			НастройкиПользователя = НовыеНастройки;
		КонецЕсли;	
	КонецЕсли;	
		
КонецПроцедуры

// Служебная процедура для сохранения пин-кода сертификата
//
// Параметры:
//  ОписаниеСертификата		- см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//  НастройкиПользователя	- см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//  ПинКод					- Строка
//  Сохранить				- Булево
//  НовыйПинКод				- Булево
//  ПараметрыОперации		- Структура
//
Процедура УстановитьПинКодСертификата(ОписаниеСертификата, НастройкиПользователя, ПинКод, Сохранить = Ложь, НовыйПинКод = Ложь, ПараметрыОперации = Неопределено)
	
	ОписаниеСертификата.ПинКод = ПинКод;
	Если НовыйПинКод Тогда 
		ОписаниеСертификата.ТребуетсяПинКод = НЕ ТребуетсяВводКонфиденциальныхДанных(ПинКод);
	КонецЕсли;	
	
	НастройкиПользователя.Сертификаты.Вставить(ОписаниеСертификата.Отпечаток, ОписаниеСертификата);
	ТекущиеНастройки = Новый Структура("Ссылка", НастройкиПользователя.Ссылка);
	СервисКриптографииDSSСлужебныйВызовСервера.ОбновитьНастройкиПользователя(ТекущиеНастройки, НастройкиПользователя, ПараметрыОперации);
	
	Если Сохранить Тогда
		СервисКриптографииDSSСлужебныйВызовСервера.СохранитьПинКодСертификата(
				НастройкиПользователя.УникальныйИдентификатор,
				ОписаниеСертификата.Отпечаток, 
				ОписаниеСертификата.ПинКод);
	КонецЕсли;
	
	НастройкиПользователя = ТекущиеНастройки;
	
КонецПроцедуры

// Служебная функция формирующая информацию о трансформации данных и ее дополняет ПараметрыОперации
//
Процедура ТрансформацияДанных(ПараметрыОперации, ТипРезультата)
	
	ТрансформироватьРезультат = СвойствоСтруктуры(ПараметрыОперации, "ТрансформироватьРезультат");
	
	Если ТипЗнч(ТипРезультата) = Тип("Структура") Тогда
		Если ТрансформироватьРезультат = Неопределено Тогда
			ПараметрыОперации.Вставить("ТрансформироватьРезультат", ТрансформироватьРезультат);
		КонецЕсли;
	Иначе	
		Если ТрансформироватьРезультат = Неопределено Тогда
			ТрансформироватьРезультат = Новый Структура;
			ТрансформироватьРезультат.Вставить("ТипРезультата", ТипРезультата);
			ПараметрыОперации.Вставить("ТрансформироватьРезультат", ТрансформироватьРезультат);
		КонецЕсли;
	КонецЕсли;	
	
КонецПроцедуры

// Функция-обертка. см. СервисКриптографииDSSКлиентСервер.ТребуетсяВводКонфиденциальныхДанных
//
Функция ТребуетсяВводКонфиденциальныхДанных(ТекущиеДанные)
	
	Возврат СервисКриптографииDSSКлиентСервер.ТребуетсяВводКонфиденциальныхДанных(ТекущиеДанные);
	
КонецФункции

// Функция для контроля вызова функций облачно подписи при включенной функциональной опции
// Если функциональная опции отключена, то возвращается Ложь и вызывается обработка оповещения
// с отрицательным результатом.
//
Функция ИспользованиеОблачнойПодписиВозможно(ВходящийКонтекст)
	
	Результат = СервисКриптографииDSSКлиент.ИспользоватьСервисОблачнойПодписи();
	
	Если НЕ Результат Тогда
		ОтветСервиса = ОтветСервисаПоУмолчанию(Ложь);
		ПредставлениеОшибки = ПолучитьОписаниеОшибки(ОтветСервиса, "ПодсистемаОтключена");
		ОбработчикВозврата = СвойствоСтруктуры(ВходящийКонтекст, "ОповещениеОЗавершении");
		Если ОбработчикВозврата = Неопределено Тогда
			ВызватьИсключение ПредставлениеОшибки;
		Иначе
			ВернутьРезультатВызова(ВходящийКонтекст, ОтветСервиса);
		КонецЕсли;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Служебная получает описание операции из настроек пользователя 
//
Функция КлючДействияОперации(ВидОперации, НастройкиПользователя)
	
	КлючДействия = СервисКриптографииDSSКлиентСервер.СвойствоВыполняемойОперации(НастройкиПользователя, ВидОперации);
	
	Возврат КлючДействия;
	
КонецФункции

// Служебная трансформирует ответ для потребителя в нужном формате и только с теми полями которые ему нужны.
//
Функция ПодготовитьПсевдонимыОтвета(РезультатВызова, ПараметрыОперации)
	
	Псевдонимы = СвойствоСтруктуры(ПараметрыОперации, "Псевдонимы");
	
	Если Псевдонимы = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Результат = Новый Структура();
	
	Для Каждого СтрокаКлюча Из Псевдонимы Цикл
		
		ЗначениеКлюча = СвойствоСтруктуры(РезультатВызова, СтрокаКлюча.Ключ);
		
		Если СтрокаКлюча.Значение = "ИнформацияОбОшибке" 
			И ЗначениеЗаполнено(ЗначениеКлюча) Тогда
			Попытка
				ВызватьИсключение СокрЛП(ЗначениеКлюча);
			Исключение
				ЗначениеКлюча = ИнформацияОбОшибке();
			КонецПопытки;	
		КонецЕсли;
		
		Результат.Вставить(СтрокаКлюча.Значение, ЗначениеКлюча);
		
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

// Служебная функций, которая определяет необходимость обработки ошибки.
//
Функция НеОбрабатыватьОшибкиСервиса(ВходящийКонтекст)
	
	Результат = СвойствоСтруктуры(ВходящийКонтекст.ПараметрыОперации, "ОбработкаОшибок", Истина);
	
	Возврат НЕ Результат;
	
КонецФункции

// Служебная для проверки запуска клиента в браузере
//
// Возвращаемое значение:
//  Булево
//
Функция ЭтоВебКлиент()
	
#Если ВебКлиент Тогда
	Возврат Истина;
#Иначе
	Возврат Ложь;
#КонецЕсли
	
КонецФункции

// Служебная для определения имени браузера с клиентом 1С
//
// Возвращаемое значение:
//  Строка
//
Функция ИмяБраузера()
	
	СисИнфо = Новый СистемнаяИнформация;
	
	ВебБраузер = СисИнфо.ИнформацияПрограммыПросмотра;
	
	Если СтрЧислоВхождений(ВРег(ВебБраузер), "MSIE") > 0 
			ИЛИ СтрЧислоВхождений(ВРег(ВебБраузер), "TRIDENT") > 0 Тогда
		
		ВебБраузер = "MSIE";
		
	ИначеЕсли СтрЧислоВхождений(ВРег(ВебБраузер), "FIREFOX") > 0 Тогда
		
		ВебБраузер = "FIREFOX";
		
	ИначеЕсли СтрЧислоВхождений(ВРег(ВебБраузер), "CHROME") > 0 Тогда
		
		ВебБраузер = "CHROME";
		
	ИначеЕсли СтрЧислоВхождений(ВРег(ВебБраузер), "SAFARI") > 0 Тогда
		
		ВебБраузер = "SAFARI";
		
	КонецЕсли;
		
	Возврат ВебБраузер;
	
КонецФункции

// Служебная для регистрации количества подряд неудачных попыток аутентификации
//
Процедура ИзменитьСчетчикПопыток(НастройкиПользователя, Успешно)
	
	Если Успешно Тогда
		НастройкиПользователя.НеудачныхПопыток = 0;
	Иначе
		НастройкиПользователя.НеудачныхПопыток = НастройкиПользователя.НеудачныхПопыток + 1;
	КонецЕсли;
	
КонецПроцедуры

// Формирует стандартный ответ применяемый в подсистеме.
//
// Параметры:
//   Выполнено 			- Булево
//   ИдентификаторОшибки - Строка
// 	
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиент.ОтветСервисаПоУмолчанию
//
Функция ОтветСервисаПоУмолчанию(Выполнено = Истина, ИдентификаторОшибки = "")
	
	Возврат СервисКриптографииDSSКлиент.ОтветСервисаПоУмолчанию(Выполнено, ИдентификаторОшибки);
	
КонецФункции

#КонецОбласти

#КонецОбласти